怎么使通过进程打开的win32程序窗口始终置顶

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎么使通过进程打开的win32程序窗口始终置顶相关的知识,希望对你有一定的参考价值。

枚举顶层(top-level)窗口枚举桌面顶层窗口相对于枚举进程来说可能要容易一些。枚举桌面顶层窗口的方法是用 EnumWindows() 函数。不要用 GetWindow()来创建窗口列表,因为窗口之间复杂的父子及同胞关系(Z-Order)容易造成混乱而使得枚举结果不准确。EnumWindows()有两个参数,一个是指向回调函数的指针,一个是用户定义的 LPARAM 值, 针对每个桌面窗口(或者顶层窗口)它调用回调函数一次。然后回调函数用该窗口句柄做一些处理,比如将它添加到列表中。这个方法保证枚举结果不会被窗口复杂的层次关系搞乱,因此,一旦有了窗口句柄,我们就可以通过 GetWindowText() 得到窗口标题。枚举进程建立系统进程列表比枚举窗口稍微复杂一些。这主要是因为所用的 API 函数对于不同的 Win32 操作系统有依赖性。在 Windows 9x、Windows Me、Windows 2000 Professional 以及 Windows XP 中,我们可以用 ToolHelp32 库中的 APIs 函数。但是在 Windows NT 里,我们必须用 PSAPI 库中的 APIs 函数, PSAPI 库是 SDK 的一部分。本文我们将讨论上述所有平台中的实现。附带的例子程序将对上述库中的 APIs 进行包装,以便包装后的函数能支持所有 Win32 操作系统。使用 ToolHelp32 库枚举进程ToolHelp32 库函数在 KERNEL32.dll 中,它们都是标准的 API 函数。但是 Windows NT 4.0 不提供这些函。ToolHelp32 库中有各种各样的函数可以用来枚举系统中的进程、线程以及获取内存和模块信息。其中枚举进程 只需用如下三个的函数:CreateToolhelp32Snapshot()、Process32First()和 Process32Next()。使用 ToolHelp32 函数的第一步是用 CreateToolhelp32Snapshot() 函数创建系统信息“快照”。这个函数可以让你选择存储在快照中的信息类型。如果你只是对进程信息感兴趣,那么只要包含 TH32CS_SNAPPROCESS 标志即可。 CreateToolhelp32Snapshot() 函数返回一个 HANDLE,完成调用之后,必须将此 HANDLE 传给 CloseHandle()。接下来是调用一次 Process32First 函数,从快照中获取进程列表,然后重复调用 Process32Next,直到函数返回 FALSE 为止。这样将遍历快照中进程列表。这两个函数都带两个参数,它们分别是快照句柄和一个  PROCESSENTRY32 结构。调用完 Process32First 或 Process32Next 之后,PROCESSENTRY32 中将包含系统中某个进程的关键信息。其中进程 ID 就存储在此结构的 th32ProcessID。此 ID 可以被传给 OpenProcess() API 以获得该进程的句柄。对应的可执行文件名及其存放路径存放在 szExeFile 结构成员中。在该结构中还可以找到其它一些有用的信息。注意:在调用 Process32First() 之前,一定要记住将 PROCESSENTRY32 结构的 dwSize 成员设置成 sizeof(PROCESSENTRY32)。使用 PSAPI 库枚举进程在 Windows NT 中,创建进程列表使用 PSAPI 函数,这些函数在 PSAPI.DLL 中。这个文件是随 Platform SDK 一起分发的,最新版本的 Platform SDK 可以从这里下载:使用这个库所需的 PSAPI.h 和 PSAPI.lib 文件也在该 Platform SDK 中。为了使用 PSAPI 库中的函数,需将 PSAPI.lib 添加到代码项目中,同时在所有调用 PSAPI API 的模块中包含 PSAPI.h 文件。记住一定要随可执行文件一起分发 PSAPI.DLL,因为它不随 Windows NT 一起分发。你可以点击这里单独下载 PSAPI.DLL 的可分发版本(不用完全下载 Platform SDK)。与 ToolHelp32 一样,PSAPI 库也包含各种各样有用的函数。由于篇幅所限,本文只讨论与枚举进程有关函数:EnumProcesses()、EnumProcessModules()、GetModuleFileNameEx()和 GetModuleBaseName()。创建进程列表的第一步是调用 EnumProcesses()。该函数的声明如下:BOOL EnumProcesses( DWORD *lpidProcess, DWORD cb, DWORD *cbNeeded );EnumProcesses()带三个参数,DWORD 类型的数组指针 lpidProcess;该数组的大小尺寸 cb;以及一个指向 DWORD 的指针 cbNeeded,它接收返回数据的长度。DWORD 数组用于保存当前运行的进程 IDs。cbNeeded 返回数组所用的内存大小。下面算式可以得出返回了多少进程:nReturned = cbNeeded / sizeof(DWORD)。注意:虽然文档将返回的 DWORD 命名为“cbNeeded”,实际上是没有办法知道到底要传多大的数组的。EnumProcesses()根本不会在 cbNeeded 中返回一个大于 cb 参数传递的数组值。结果,唯一确保 EnumProcesses()函数成功的方法是分配一个 DWORD 数组,并且,如果返回的 cbNeeded 等于 cb,分配一个较大的数组,并不停地尝试直到 cbNeeded 小于 cb现在,你获得了一个数组,其元素保存着系统中每个进程的ID。如果你要想获取进程名,那么你必须首先获取一个句柄。要想从进程 ID 得到句柄,就得调用 OpenProcess()。一旦有了句柄,则需要得到该进程的第一个模块。为此调用 EnumProcessModules() API:EnumProcessModules( hProcess, &hModule, sizeof(hModule), &cbReturned );  调用之后,hModule 变量中保存的将是进程中的第一个模块。记住进程其实没有名字,但进程的第一个模块既是该进程的可执行模块。现在你可以用 hModule 中返回的模块句柄调用 GetModuleFileNameEx() 或 GetModuleBaseName() API 函数获取全路径名,或者仅仅是进程可执行模块名。两个函数均带四个参数:进程句柄,模块句柄,返回名字的缓冲指针以及缓冲大小尺寸。用 EnumProcesses() API 返回的每一个进程 ID 重复这个调用过程,你便可以创建 Windows NT 的进程列表。16位进程的处理方法在 Windows 95,Windows 98 和 Windows ME 中,ToolHelp32 对待16位程序一视同仁,它们与 Win32 程序一样有自己的进程IDs。但是在 Windows NT,Windows 2000 或 Windows XP 中情况并不是这样。在这些操作系统中,16位程序运行在所谓的 VDM 当中(也就是DOS机)。为了在 Windows NT,Windows 2000 和 Windows XP 中枚举16位程序,你必须使用一个名为 VDMEnumTaskWOWEx()的函数。在源代码模块中必须包含 VDMDBG.h,并且 VDMDBG.lib 文件必须与项目链接。这两个文件都在 Platform SDK 中。该函数的声明如下:INT WINAPI VDMEnumTaskWOWEx( DWORD dwProcessId, TASKENUMPROCEX fp,LPARAM lparam );此处 dwProcessId 是 NTVDM 中拟枚举的16位任务进程标示符。参数 fp 是回调枚举函数的指针。参数 lparam 是用户定义的值,它被传递到枚举函数。枚举函数应该被定义成如下这样:BOOL WINAPI Enum16( DWORD dwThreadId,          WORD hMod16,          WORD hTask16,          PSZ pszModName,          PSZ pszFileName,          LPARAM lpUserDefined );  该函数针对每个运行在 NTVDM 进程中的16位任务调用一次,NTVDM 进程ID将被传入 VDMEnumTaskWOWEx()。如果想继续枚举则返回 FALSE,终止枚举则返回 TRUE。注意这是与 EnumWindows()相对的。关于代码本文附带的代码例子将 PSAPI 和 ToolHelp32 封装到一个名为 EnumProcs() 的函数中。该函数的工作原理类似 EnumWindows(),有一个指向回调函数的指针,并要对该函数进行重复调用,针对系统中的每个进程调用一次。另一个参数是用户定义的 lParam。下面是该函数的声明:BOOL WINAPI EnumProcs( PROCENUMPROC lpProc, LPARAM lParam );使用该函数时,要象下面这样声明回调函数:BOOL CALLBACK Proc( DWORD dw, WORD w16, LPCSTR lpstr, LPARAM lParam );参数 dw 包含 ID,“w16”是16位任务的任务号,如果为32位进程则为0(在 Windows 95 中总是0),参数lpstr 指向文件名,lParam 是用户定义的,要被传入 EnumProcs()。EnumProcs() 函数通过显示链接使用 ToolHelp32 和 PSAPI,而非通常所用的隐式链接。之所以要这样做,主要是为了让代码能够在二进制一级兼容,从可以在所有 Win32 操作系统平台上运行。 参考技术A findwindow 找到窗口
setwindowpos swp_topmost 置顶

tkinter 关闭窗口怎么把整个程序都结束??

请问一下,写了一个程序,里面有def函数,其中有一个是调用tkinter窗口输入数据的,要怎么让这个窗口被点击右上角X的时候把整个程序结束呢??程序长了些,对应tkinter的部分如下:
def face():
win = tk.Tk()
win.title('名称')
center_window(win, 300, 150)#此处是单独写的另一个窗口居中的函数
win.wm_attributes('-topmost',1)#置顶
win.resizable(width=False, height=False)
tk.Label(win,text=" ").pack()
tk.Label(win,text="输入名称:").pack()
var = tk.StringVar()
tk.Entry(win,textvariable = var).pack()
tk.Label(win,text=" ").pack()
B=tk.Button(win,text='确定',width=8,command=win.destroy)
win.bind('<Return>', lambda e: win.destroy())
B.pack()
win.mainloop()
return(var.get())

这个函数写的是获得一个名称的值,但是关闭tkinter的窗口时程序就出现假死的状态,要怎么实现点击右上角的X 就结束整个程序呢?

把另一个窗口的设置为主窗口的子窗口。
代码:主窗口.Toplevel(子窗口)
把原来的 子窗口.Tk() 替换掉就好了。
还想问一下楼主,,我在tkinter打开turtle,在没画完的情况下关闭turtle,就会一直再弹出turtle窗口直到原来的指令执行完为止,关闭主窗口也没用。不知道该怎么解决。
参考技术A 因为mainloop()没有收到消息要退出循环。
在你完成任务后调用root.destroy()即可退出循环。点右上角的x也是一样的。追问

你好,我不是要结束这个窗口,我是要结束整个程序,这个def只是程序众多中的一个

以上是关于怎么使通过进程打开的win32程序窗口始终置顶的主要内容,如果未能解决你的问题,请参考以下文章

VB怎么使外调程序置顶

win32两个应用程序窗口之间进行进程通信要怎么写

python 通过js控制滚动条拉取全文 通过psutil获取pid窗口句柄,通过win32gui使程序窗口前置 通过pyauto实现右键菜单和另存为操作

vb取消窗口置顶

怎么用c语言在windows下弹出一个置顶的窗口?

MFC 如何使窗口 置顶