| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4194 人关注过本帖, 2 人收藏
标题:VFP 如何设定当前窗口是活动窗口?(有时候窗口在最前,但焦点在桌面上)
只看楼主 加入收藏
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10607
专家分:43186
注 册:2014-5-20
收藏
得分:0 
用SetForegroundWindow()线程间切换前台窗口、AttachThreadInput()切换键盘输入焦点。

DECLARE LONG SetForegroundWindow IN user32 LONG
DECLARE LONG GetForegroundWindow IN user32
DECLARE LONG GetCurrentThreadId IN kernel32
DECLARE LONG GetWindowThreadProcessId IN user32 LONG, LONG
DECLARE LONG AttachThreadInput IN user32 LONG, LONG, LONG
DECLARE LONG ShowWindow IN user32 LONG, LONG

** Timer1.Timer
hForeWnd = GetForegroundWindow()

IF hForeWnd != thisform.hWnd
    dwCurID  = GetCurrentThreadId()
    dwForeID = GetWindowThreadProcessId(hForeWnd, 0)
    AttachThreadInput(dwCurID, dwForeID, .T.)
    ShowWindow(thisform.hWnd, 1)
    SetForegroundWindow(thisform.hWnd)
    AttachThreadInput(dwCurID, dwForeID, .F.)
ENDIF

[ 本帖最后由 吹水佬 于 2014-6-29 22:24 编辑 ]
2014-06-29 22:22
liuxingang28
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:山东济南
等 级:贵宾
威 望:47
帖 子:658
专家分:2180
注 册:2014-2-7
收藏
得分:0 
回复 11 楼 吹水佬
经检测:在 XP 下运行,只有将表单设为“顶层表单”、且将表单的 AlwaysOnTop 属性为 .t. 时,才可以达到所要的效果,也就是说,API函数AttachThreadInput()没有起到自动激活目标窗口的功能。

测试标准:
1. 单击其他应用程序窗口后,系统可自动切换回目标窗口
2. 单击目标窗口的最小化按钮后,系统可自动还原窗口(若原窗口最大化,您的代码是将窗口恢复到正常大小,而不是恢复到最大化状态)

该问题也困扰了我很久,试了很多 API 函数都没有成功,最后只能通过设置表单或_Screen的 AlwaysOnTop=.t.绕过了此问题。对您的不懈探索精神敬礼!

泉城飞狐
2014-06-30 11:39
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10607
专家分:43186
注 册:2014-5-20
收藏
得分:0 
XP SP3 和 Win8.1 试过还可以,可能是表单参数设置问题? 还是被其他应用接管了?
目标窗口状态按自己需要去控制就可以。

本测试直接在表单设计器创建Form1和运行
form1.WindowType = 1
form1.ShowWindowType = 2

* form1.Load
_SCREEN.Visible = .F.
DECLARE LONG SetForegroundWindow IN user32 LONG
DECLARE LONG GetForegroundWindow IN user32
DECLARE LONG GetCurrentThreadId IN kernel32
DECLARE LONG GetWindowThreadProcessId IN user32 LONG, LONG
DECLARE LONG AttachThreadInput IN user32 LONG, LONG, LONG
DECLARE LONG ShowWindow IN user32 LONG, LONG
DECLARE LONG SetWindowPos IN user32 LONG, LONG, LONG, LONG, LONG, LONG, LONG
DECLARE LONG SystemParametersInfo IN user32 LONG, LONG, LONG@, LONG
DECLARE LONG PostMessage IN user32 LONG, LONG, LONG, LONG

* form1.UnLoad
this.Tag = "1"
CLEAR DLLS
_SCREEN.Visible = .T.

* form1.Timer1.Interval = 1000
* form1.Timer1.Timer
hForeWnd = GetForegroundWindow()
IF hForeWnd != thisform.hWnd
    dwCurID  = GetCurrentThreadId()
    dwForeID = GetWindowThreadProcessId(hForeWnd, 0)
    AttachThreadInput(dwCurID, dwForeID, .T.)
    ShowWindow(thisform.hWnd, 1)    && SW_SHOWNORMAL
    *SetWindowPos(thisform.hWnd, -1, 0,0,0,0, 3)
    *SetWindowPos(thisform.hWnd, -2, 0,0,0,0, 3)
    SetForegroundWindow(thisform.hWnd)
    AttachThreadInput(dwCurID, dwForeID, .F.)
ENDIF


也试过拦截 WM_KILLFOCUS 消息,事件处理要加延时和异步消息模式,有点不解?

* form1 自定义 killfocus 和 setfocus 方法
* form1.Init
BINDEVENT(this.hWnd, 8, this, "killfocus")
BINDEVENT(this.hWnd, 0x401, this, "setfocus")

* form1.killfocus
LPARAMETERS hWnd, nMsg, wParam, lParam
IF this.Tag == "1"
    RETURN
ENDIF
PostMessage(hWnd, 0x401, 0, 0)    && 不这样键盘光标不见了?

* form1.setfocus
LPARAMETERS hWnd, nMsg, wParam, lParam
*nTimeout = 0
*SystemParametersInfo(0x2000, 0, @nTimeout, 3)
INKEY(0.5)    && 这时要加延时?
hForeWnd = GetForegroundWindow()
dwCurID  = GetCurrentThreadId()
dwForeID = GetWindowThreadProcessId(hForeWnd, 0)
AttachThreadInput(dwCurID, dwForeID, .T.)
ShowWindow(hWnd, 1)    && SW_SHOWNORMAL
*SetWindowPos(hWnd, -1, 0,0,0,0, 3)
*SetWindowPos(hWnd, -2, 0,0,0,0, 3)
SetForegroundWindow(hWnd)
AttachThreadInput(dwCurID, dwForeID, .F.)
2014-06-30 15:18
mywisdom88
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:191
帖 子:3147
专家分:8408
注 册:2015-3-25
收藏
得分:0 
学习
2016-04-16 20:31
快速回复:VFP 如何设定当前窗口是活动窗口?(有时候窗口在最前,但焦点在桌面上 ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.023419 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved