【问】除了定时查询以外,如何知道改变了当前焦点窗体?(如:从记事本切换到了IE)
问题点数:20、回复次数:8Top
1 楼henry520()回复于 2004-12-13 16:05:50 得分 1
关注Top
2 楼yiway(一味)回复于 2004-12-13 16:08:59 得分 2
关注,
鄙人愚见:应该可以通过系统调用解决,具体方法学习中Top
3 楼wwqna(york)回复于 2004-12-13 18:02:20 得分 1
没办法,只有查询Top
4 楼VBAHZ(凌云(E文词汇量580))回复于 2004-12-19 14:04:50 得分 0
GZ
Top
5 楼myjian(嗷嗷叫的老马--很不顺.....最近.....很不顺.........)回复于 2004-12-19 20:20:00 得分 10
晕,Windows整个都是消息方式来执行的啊,怎么会只能查询啊。
正好我给一个朋友做了一个网吧管理系统里有这样的功能:记录当前焦点的窗体的句柄,记录切换到了哪个窗体。
代码摘自网上,如下:
*******************************************
' 窗体部分的代码(Form1.frm)
Option Explicit
Private Sub Form_Load()
Dim tmp As Long
' 将日志程序的名称从 CTRL+ALT+DEL 列表中清除
'tmp = RegisterServiceProcess(ByVal 0&, 1)
Timer1.Interval = 60000 ' 定时器的作用是每隔一分钟将日志存盘
' 定义一个新的系统级的消息类型
Msg_ID = RegisterWindowMessage("SHELLHOOK")
Call RegisterShellHook(hwnd, 1) ' 调用未公开的函数(进行注册)
' 实施拦截:在存储了原入口地址的同时,将新地址指向自定义的函数WindowProc
Original = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)
SetWindowPos Me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE
' 将窗口设为总在最前
End Sub
Private Sub Form_Unload(Cancel As Integer)
Dim tmp As Long
Call RegisterShellHook(hwnd, 0) ' 调用未公开的函数(取消注册)
'tmp = SetWindowLong(hwnd, GWL_WNDPROC, Original) ' 将入口地址还原
End Sub
**************************
' 模块部分的代码(模块1.bas)
Public Declare Function RegisterShellHook Lib "Shell32" Alias "#181" _
(ByVal hwnd As Long, ByVal nAction As Long) As Long
Public Declare Function RegisterWindowMessage Lib "user32" Alias _
"RegisterWindowMessageA" (ByVal lpString As String) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
(ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal _
wParam As Long, ByVal lParam As Long) As Long
Public Declare Function RegisterServiceProcess Lib "kernel32" _
(ByVal dwProcessID As Long, ByVal dwType As Long) As Long
Const HSHELL_WINDOWCREATED = 1 ' 系统级的窗体被创建
Const HSHELL_WINDOWDESTROYED = 2 ' 系统级的窗体即将被关闭
'Const HSHELL_ACTIVATESHELLWINDOW = 3 ' SHELL 的主窗体将被激活(本例未用)
Const HSHELL_WINDOWACTIVATED = 4 ' 系统级的窗体被激活
'Const HSHELL_GETMINRECT = 5 ' 窗体被最大化或最小化(本例未用)
'Const HSHELL_REDRAW = 6 ' Windows 任务栏被刷新(本例未用)
'Const HSHELL_TASKMAN = 7 ' 任务列表的内容被选中(本例未用)
'Const HSHELL_LANGUAGE = 8 ' 中英文切换或输入法切换(本例未用)
Public Const GWL_WNDPROC = -4 ' 该索引用来创建窗口类的子类
Public Msg_ID As Long, Original As Long
Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal _
wParam As Long, ByVal lParam As Long) As Long ' 回调函数
Dim tmp1 As String, tmp2 As String, i As Long
If uMsg = Msg_ID Then
tmp1 = String(200, "*")
i = GetWindowText(lParam, tmp1, 200) ' 取窗体的标题
If i > 0 Then tmp1 = Left(tmp1, i) Else tmp1 = "未命名"
tmp1 = tmp1 + " " + Str(Date) + " " + Str(Time) + vbCrLf ' 加入日期
' 下面对窗体句柄值进行格式化的目的是为了日志文件在视觉上更美观
tmp2 = Format(lParam, "000000")
If Right(Form1.Text1, 2) <> vbCrLf Then tmp2 = vbCrLf + tmp2
Select Case wParam
Case HSHELL_WINDOWCREATED
Form1.Text1 = Form1.Text1 + tmp2 + " 创建:" + tmp1
Case HSHELL_WINDOWDESTROYED
Form1.Text1 = Form1.Text1 + tmp2 + " 关闭:" + tmp1
Case HSHELL_WINDOWACTIVATED
Form1.Text1 = Form1.Text1 + tmp2 + " 激活:" + tmp1
' 为了程序简洁,本例仅处理“创建”、“激活”和“关闭”这三个消息,
' 其实就生成日志文件的目的,上述三个消息已基本够用。
' Case ...
' ...
End Select
Else
' 使用已被存储下来的原入口地址
WindowProc = CallWindowProc(Original, hwnd, uMsg, wParam, lParam)
End If
End Function
***********************************
'*************************************************************************
'**模 块 名:ModOnTop
'**说 明:将窗体放到Z轴最上层
'**创 建 人:马云剑
'**日 期:2004年10月27日
'**修 改 人:
'**日 期:
'**描 述:
'**版 本:V1.0
'*************************************************************************
Public Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Public Const HWND_TOPMOST& = -1
' 将窗口置于列表顶部,并位于任何最顶部窗口的前面
Public Const SWP_NOSIZE& = &H1
' 保持窗口大小
Public Const SWP_NOMOVE& = &H2
' 保持窗口位置
'**************
'* 使用方法 *
'**************
'在窗体Load事件里加入以下代码:
'SetWindowPos Me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE
' 将窗口设为总在最前
Top
6 楼myjian(嗷嗷叫的老马--很不顺.....最近.....很不顺.........)回复于 2004-12-19 20:22:20 得分 3
窗体部分还有一个过程忘了帖:
***********************************
Private Sub Timer1_Timer()
If Len(Text1.Text) > 0 Then
Open "C:\SystemLog.Sys" For Append As #1 ' 以“添加”方式打开日志
Print #1, Text1.Text ' 日志自动存盘
Text1.Text = ""
Close #1
End If
End Sub
Top
7 楼myjian(嗷嗷叫的老马--很不顺.....最近.....很不顺.........)回复于 2004-12-19 20:25:29 得分 3
这个代码在运行时,可以显示当前都切换了哪些焦点,以及焦点的标题。
但这个好像是用的子类,我不懂......
请大家解释一下什么是子类......
还有这个代码也请分析一下!!!3Q!Top
8 楼VBAHZ(凌云(E文词汇量580))回复于 2004-12-19 20:57:23 得分 0
就是这个,多谢!
子类嘛。。。俺也老菜一个,就俺的理解:
子类就是把送给窗体的消息,转到自己的代码段(形成了一个子“进程”?“类”?),处理自己想要接收到的信息,并把无关消息再扔给原窗体消息处理(VB的优势,就是封装了这一切细节,编程者无需关心消息过程)
本例来说,上面的代码是我看到的中文注释最多的一例(好久没这么亲切了,中文真好:),除去API定义外,没有几句了,应该很简单的,但助人为。。那个什么本啊,老兄具体哪里不明白请说,三个臭皮匠凑起来也够亮吧,呵呵
Top




