none
利用VB编写屏幕保护程序(1) RRS feed

  • 常规讨论

  • 相同则关闭此次运行的实例。

      显然要实现这种方法靠VB的App.PrevInstance是不可行的。因为我们要达到的目的是:侦测到前一个实例后要关闭它然后启动程序。而App.PrevInstance属性只能返回当前是否已启动一个应用程序的实例而不能对前个实例做些什么。(实例 简单地说就是相同的对象集合——同一程序。)在实现此方法之前首先向大家介绍三条API函数:GetClassName、FindWindow和SendMessage。其原型如下:

      Declare Function GetClassName Lib “user32” Alias “GetClassNameA” (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
      Declare Function FindWindow Lib “user32” Alias “FindWindowA” (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
      Declare Function SendMessage Lib “user32” Alias “SendMessageA” (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
      GetClassName用于取得窗体的类名。调用成功后返回类名长度,失败返回零。函数需要三个参数:参数一.窗体的句柄,参数二.存放类名的缓冲,参数三.缓冲的大小。

      FindWindow用于寻找窗体。调用成功后返回窗体的句柄,失败返回零。函数需要两个参数:参数一.窗体的类名,参数二.窗体的标题。

      SendMessage用于向窗体发送一消息。函数需要四个参数:参数一.窗体的句柄,参数二:发送的消息名称,参数三、四.分别表示消息所附带的参数。

      使用了这三个函数便可轻易地实现关闭前有一个已启动的实例从而达到我们的目的。

      其次我们要实现如何让屏幕保护程序显示在预览框中(“小屏幕”)。

      要让屏幕保护程序在预览框中显示必须动态地改变窗口的样式使之成为“小屏幕”的子窗体,这样才能使预览框关闭时得到关闭消息。动态地改变窗口的样式可以使用GetWindowLong、SetWindowLong和SetParent。

      它们的原型如下:

      Public Declare Function GetWindowLong Lib “user32” Alias “GetWindowLongA” (ByVal hwnd As Long, ByVal nIndex As Long) As Long Public Declare Function SetWindowLong Lib “user32” Alias “SetWindowLongA” (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Declare Function SetParent Lib “user32” (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long

      GetWindowLong的作用用于得到窗体的样式。调用成功后返回窗体的样式。函数需要两个参数:参数一.窗体的句柄,参数二.要取得窗体的样式只需使用常数GWL_STYLE。

      SetWindowLong的作用用于设置窗体的样式。函数需要三个参数:参数一.窗体的句柄,参数二.要设置窗体的样式只需用常数GWL_STYLE,参数三.要设置窗体的样式。

      SetParent的作用用于设置子窗体属于哪个父窗体。函数需要两个参数:参数一.子窗体的句柄,参数二.父窗体的句柄。

      知道了以上两点就可编写出标准的屏保。(关于效果就看你自己的了!)纸上谈兵了一阵就要落实到真正的编程上了。为了着重讲解屏保的实现方法故将屏保的效果简单化。

      首先新建一工程再添加一窗口,各属性设置如下:



       窗口   名称    Caption BorderStyle
       Form1   Frm_Setup   无 1 - None
       Form2   Frm_Run  任意 1 - Fixed Single
      其余属性均缺省。再在Frm_Run中添加一Timer控件,将该控件的名称改为Timer_Mov,Interval属性制改为500。

      添加两个模块,将Module1的名称改为Mod_Const,Module2的名称改为Mod_Main,添加以下代码:

      Mod_Const:
      Option Explicit
      Public Const WM_LOOK=“屏保预览(demo)”
      Public Const WM_SET=“屏保设置(demo)”
      Public Const WM_RUN=“屏保运行(demo)”
      Public Const HWND_TOP=0&
      Public Const WS_CHILD=&H40000000
      Public Const GWL_STYLE=(-16)
      Type RECT
       Left As Long
       Top As Long
       Right As Long
       Bottom As Long
      End Type
      
      Public Const SWP_NOZORDER=&H4
      Public Const SWP_NOACTIVATE=&H10
      Public Const SWP_SHOWWINDOW=&H40
      
      Public Const WM_CLOSE=&H10
      
      Declare Function GetClientRect Lib “user32” (ByVal hwnd As Long, lpRect As RECT) As Long
      Declare Function GetClassName Lib “user32” Alias “GetClassNameA” (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
      Declare Function FindWindow Lib “user32” Alias “FindWindowA” (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
      Declare Function SendMessage Lib “user32” Alias “SendMessageA” (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
      Declare Function SetParent Lib “user32” (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
      Public Declare Function GetWindowLong Lib “user32” Alias “GetWindowLongA” (ByVal hwnd As Long, ByVal nIndex As Long) As Long
      Public Declare Function SetWindowLong Lib “user32” Alias “SetWindowLongA” (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
      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
      Declare Function ShowCursor Lib “user32” (ByVal bShow As Long) As Long
      
      Mod_Main:
      
      Option Explicit   

      Sub Main() 注释:程序运行入口
      Dim ClassName As String * 64 存放窗口的类名
      Dim ExeCmd As String 注释:存放命令行参数
      
      GetClassName Frm_Setup.hwnd, ClassName, 64 取得窗口的类名
      ExeCmd=UCase(Command$) 将调用的屏保的参数转换成大写后存放在变量ExeCmd里
      If Not (InStr(ExeCmd,“/P”)=0)Then 检查屏保的调用参数中是否有“/P”参数
      If Not (FindWindow(ClassName, WM_LOOK)=0)Then End 如果找到已有同一个运行方式的实例存在则程序结束
    2009年5月27日 8:26