注册 登录
编程论坛 VFP论坛

请教吹版主关于API函数 openprocess

kmyz_yyl 发布于 2023-07-04 22:59, 1527 次点击

请教吹版主,我在https://www.看到这段VB代码,想借此实现在多个打开的EXCEL文档中找到需要关闭的文档,然后在转成VFP后在下面代码 ??处始终出错,请教是解决办法
Declare Long FindWindowEx IN user32 long hWnd1, long hWnd2, string lpsz1, string lpsz2
DECLARE Long PostMessage IN WIN32API as PostMessageA Long hWnd, Long Msg, Long wParam, Long lParam
Declare INTEGER GetWindowText IN User32 long hWnd, string lpString , long cch
Declare INTEGER GetWindowThreadProcessId in user32 long hwnd, long lpdwProcessId
Declare INTEGER OpenProcess in kernel32 long dwDesiredAccess, long bInheritHandle, long dwProcessId
Declare INTEGER TerminateProcess in kernel32 long hProcess, long uExitCode
*Declare INTEGER RtlAdjustPrivilege in ntdll AND Privilege&, ByVal NewValue&, ByVal NewThread&, OldValue&)
#define WM_CLOSE = &H10
#define PROCESS_TERMINATE = &H1

hWnd = FindWindow("XLMAIN", null)         
procId=0
iid=GetWindowThreadProcessId(hWnd, @procId)
DO While hWnd <> 0
    strText = Space(256)
    GetWindowText(hWnd, @strText, Len(strText))
    strText = Left(strText, at("-",strText ) - 1)   
    If at("Microsoft Excel",strText,1) > 0 Then   
        procId = 0
        iid=GetWindowThreadProcessId(hWnd, procId)

        hProcess = OpenProcess(PROCESS_ALL_ACCESS ,0,iid)    &&  ??

        iRet = TerminateProcess(hProcess, 0)
        iRet = PostMessage(hWnd, WM_CLOSE, 0, 0)
    EndIf
enddo
18 回复
#2
csyx2023-07-05 05:49
唉,这段代码问题实在多不胜数

以下是引用kmyz_yyl在2023-7-4 22:59:40的发言:
#define WM_CLOSE = &H10
#define PROCESS_TERMINATE = &H1
vfp 有 &h 这种表示16进制法吗?

以下是引用kmyz_yyl在2023-7-4 22:59:40的发言:
hWnd = FindWindow("XLMAIN", null)         
procId=0
iid=GetWindowThreadProcessId(hWnd, @procId)
FindWindow 在哪声明的?后面两句有意义吗?hWnd 为零时咋整?

以下是引用kmyz_yyl在2023-7-4 22:59:40的发言:
DO While hWnd <> 0
 ...
enddo
hWnd 不为零的话,岂不是要死循环?

以下是引用kmyz_yyl在2023-7-4 22:59:40的发言:
        procId = 0
        iid=GetWindowThreadProcessId(hWnd, procId)
        hProcess = OpenProcess(PROCESS_ALL_ACCESS ,0,iid)    &&  ??
OpenProcess 要传入的是进程 id, 为何要传入线程id ?

以下是引用kmyz_yyl在2023-7-4 22:59:40的发言:
        iRet = TerminateProcess(hProcess, 0)
        iRet = PostMessage(hWnd, WM_CLOSE, 0, 0)
进程都杀死了,还有窗口值得关闭?
#3
吹水佬2023-07-05 07:01
回复 楼主 kmyz_yyl
看似是想枚举窗口,但又与进程相关?
枚举窗口判断从窗口类入手,不同版本的Excel主窗口类名兼容性有无问题?
参考示例:
程序代码:

DECLARE long GetWindow       IN user32 long,long
DECLARE long GetWindowText   IN user32 long,string@,long
DECLARE long GetClassName    IN user32 long,string@,long
DECLARE long IsWindowVisible IN user32 long
DECLARE long SendMessage     IN user32 long,long,long,long

#define GW_HWNDFIRST   0
#define GW_HWNDNEXT    2
#define WM_CLOSE       0x10

xls = "Book1.xls"
buf = SPACE(256)
hWnd = GetWindow(_vfp.hWnd, GW_HWNDFIRST)
DO WHILE hWnd != 0
    IF IsWindowVisible(hWnd) == 1
        len = GetClassName(hWnd, @buf, 256)
        IF LEFT(buf,len)=="XLMAIN"
            len = GetWindowText(hWnd, @buf, 256)
            IF AT(xls,LEFT(buf,len)) != 0
                SendMessage(hWnd, WM_CLOSE, 0, 0)
            ENDIF
         ENDIF
    ENDIF
    hWnd = GetWindow(hWnd, GW_HWNDNEXT)
ENDDO

#4
kmyz_yyl2023-07-05 09:22
回复 3楼 吹水佬
感谢回复的两位老师!
能否请吹版主再优化一下代码,给一下过滤出的各个BUF的句柄?

[此贴子已经被作者于2023-7-5 09:55编辑过]

#5
吹水佬2023-07-05 10:19
回复 4楼 kmyz_yyl
结果就是所有 SendMessage(hWnd, WM_CLOSE, 0, 0) 的 hWnd
#6
kmyz_yyl2023-07-05 22:46
回复 5楼 吹水佬
谢谢,我用hWnd放到EnumWindows函数下,成功遍历出全部打开的EXCEL文档了。
#7
吹水佬2023-07-05 23:38
以下是引用kmyz_yyl在2023-7-5 22:46:38的发言:

谢谢,我用hWnd放到EnumWindows函数下,成功遍历出全部打开的EXCEL文档了。

请问,VFP是怎样调用用EnumWindows函数?
#8
foxfans2023-07-06 01:10
vfp2c32.fll库中有丰富的函数,回调,多线程等.
https://
只有本站会员才能查看附件,请 登录
#9
吹水佬2023-07-06 06:38
以下是引用kmyz_yyl在2023-7-5 09:22:23的发言:

能否请吹版主再优化一下代码,给一下过滤出的各个BUF的句柄?

不只是要枚举EXCEL的窗口,还要考虑有无能打开xls的其他应用程序,这个问题就复杂点。
还有就是枚举过程完成后还有无可能会被打开。
#10
kmyz_yyl2023-07-07 22:02
回复 9楼 吹水佬
我在您给的代码里加了这句  =EnumWindowsProc(hwnd, NULL)
然后做了一个过程,如下:

PROCEDURE EnumWindowsProc
PARAMETERS hwndv,lParamv
s   =SPACE(128)+CHR(0)
*buf = SPACE(256)+CHR(0)
GetWindowText(hwndv,@s,256)
WAIT WINDOW s
WAIT window "EnumWindowsProc:"+STR(hwndv)   
=getwindowtext(hwndv,s,80)
s=LEFT(s,AT(CHR(0),s)-1)
v=getwindow(hwndv,gw_owner)
a=iswindowvisible(hwndv)
IF LEN(s)>0 AND a<>0 AND v=0
    WAIT WINDOW s
ENDIF
EnumWindowsProc =.t.
ENDPROC
#11
kmyz_yyl2023-07-07 22:07
但是过滤出来的S (EXCEL文档名),用FINDWINDOW 死活得不到这个S 的句柄,请问吹版主这又是怎么回事,如何解决?
如果能用FINDWINDOW得到过滤出的EXCEL文档句柄,那么就可以随心关闭打开的任意EXCEL文档了。

[此贴子已经被作者于2023-7-7 22:22编辑过]

#12
吹水佬2023-07-08 06:39
回复 11楼 kmyz_yyl
先观察一下s是不是你想要的
=getwindowtext(hwndv,s,80)
试改为:
=getwindowtext(hwndv,@s,80)
#13
easyppt2023-07-08 08:22
借LZ的宝贴,我想再提一下我之前发的帖子:就是VFP如何获取非VFP打开的EXCEL对象并加以控制,始终没解决。

#14
csyx2023-07-08 09:28
以下是引用easyppt在2023-7-8 08:22:30的发言:
VFP如何获取非VFP打开的EXCEL对象并加以控制,始终没解决。

给你指条路
1. 遍历所有的 XLMAIN 窗口
2. 对找到的每个 XLMAIN 窗口 > 子窗口 XLDESK > 再找 book 子窗口(类名为 EXCEL7)
3. 对找到的 book 子窗口, AccessibleObjectFromWindow 转为 book 对象, book.Application 即为 Excel对象
#15
kmyz_yyl2023-07-08 22:05
回复 12楼 吹水佬
得到了句柄,但 PostMessage( m.hWnd, WM_CLOSE, 0, 0)  或  SendMessage( m.hWnd, WM_CLOSE, 0, 0) 都提示“缺少操作数”,请吹版主和各位高手指点一下,谢谢!

之前的代码我也是用FINDWINDOW得到的句柄,然后用postmessage关闭的EXCEL文档,但今天虽然也获得了句柄却出错误提示

[此贴子已经被作者于2023-7-8 22:09编辑过]

#16
吹水佬2023-07-08 22:47
回复 15楼 kmyz_yyl
给代码测试好了
#17
kmyz_yyl2023-07-08 23:26
回复 16楼 吹水佬
我说了,因为代码是测试用,

[此贴子已经被作者于2023-7-9 15:31编辑过]

#18
kmyz_yyl2023-07-08 23:34
不知什么原因,突然之间就可以删除了,真是奇怪。


[此贴子已经被作者于2023-7-8 23:35编辑过]

#19
吹水佬2023-07-09 10:43
给出的代码感觉思路有点乱,如:
        len_= GetClassName(hWnd, @buf, 256)
        hMain=FindWindow(buf,null)
hWnd是某个窗口,取这个窗口的类名,再按这个类名找窗口。如果这个“类名”当前窗口序列中只有一个,这时hWnd==hMain,否则就有可能hWnd!=hMain,也就是说hWnd与hMain有可能不是同属一个窗口体系、两者是没有关系的窗口。取得hWnd就可以了,无需再去绕圈。

另,查找到主窗口为何还要找子窗口,关闭主窗口应该会同时释放子窗口。

简单点遍历一下窗口就应该看到有想要有窗口
1