首页 > 代码库 > TopWnd一键置顶窗口的实现,分享源码

TopWnd一键置顶窗口的实现,分享源码

TopWnd为一款精小实用的绿色软件,可以置顶大部分的窗口,一键置顶,一键取消!

贴上下载地址:

我一直都在实用这个小工具,今日好奇,决定一探其内部究竟如何实现。

网上搜索一番,没有找到这个小工具的源码。

无奈只好一步步的自己去实现它。


 

最终用MFC+全局钩子成功模仿了一个相差无几的程序。


 

  1. 准备工作
    • visual studio 2012
    • 建MFC工程
    • 拖几个控件
    • 参考文章:http://blog.csdn.net/friendan/article/details/12168273
  2. 全局钩子
    • 源码目录下有,MouseHook.dll
    • 在dll程序中,自定义一个消息,如下所示:

      • #define WM_MYMSG WM_USER + 305 //自定义消息,用于和主程序通信
    • 在钩子安装函数中,保存主程序的窗口句柄,代码如下:
      • BOOL WINAPI StartHookMouse(HWND hWnd)  {      g_hWnd=hWnd;      hhkMouse=::SetWindowsHookEx(WH_MOUSE_LL,LowLevelMouseProc,g_hInstDll,0);      if (hhkMouse==NULL)      {          return FALSE;      }       else      {          return TRUE;      }  }  
    • 在鼠标钩子响应函数中,我们将捕获到的消息,发送给主程序,代码如下:
      • LRESULT CALLBACK LowLevelMouseProc(                             int nCode,      // hook code                             WPARAM wParam,  // message identifier                             LPARAM lParam   // mouse coordinates                             )  {        //有鼠标消息时,将其发给主程序      if (g_hWnd!=NULL&&nCode==HC_ACTION)      {          ::SendMessage(g_hWnd,WM_MYMSG,wParam,lParam);      }      return CallNextHookEx(hhkMouse,nCode,wParam,lParam);  }  
  3. 处理主程序与钩子DLL的通信
    • 在主程序头文件定义一个消息与dll定义的一样
      • #define WM_MYMSG WM_USER + 305
    • 在头文件中声明消息处理函数
      • afx_msg LRESULT OnMyMsg(WPARAM wParam,LPARAM lParam);
    • 在主文件中写消息映射
      • ON_MESSAGE(WM_MYMSG,OnMyMsg)
    • 实现消息处理函数,在函数内实现置顶与恢复功能
      • LRESULT CHookMouseTestDlg::OnMyMsg(WPARAM wParam,LPARAM lParam){}

  4. 主程序实现控制
    • 打开与dll的连接函数
      •  1     //加载钩子DLL 2     g_hInstDll=LoadLibrary(_T("MouseHook.dll")); 3     if(g_hInstDll==NULL) 4     { 5         AfxMessageBox(_T("no MouseHook.dll")); 6         return; 7     } 8  9     typedef BOOL (CALLBACK *StartHookMouse)(HWND hWnd); 10     StartHookMouse StartHook;11 12     StartHook=(StartHookMouse)::GetProcAddress(g_hInstDll,"StartHookMouse");13     if(StartHook==NULL)14     {15         AfxMessageBox(_T("func StartHookMouse not found!"));16         return;17     }18 19     //将本程序的句柄传给 钩子DLL,用来通信20     if (StartHook(this->m_hWnd))21     {22         SetDlgItemText(IDC_STATE,STATE1);23     }24     else25     {26         SetDlgItemText(IDC_STATE,STATE2);27     }

         

    • 关闭与dll的连接函数
      • typedef VOID (CALLBACK *StopHookMouse)();    StopHookMouse StopHook;    g_hInstDll = LoadLibrary(_T("MouseHook.dll"));    StopHook = (StopHookMouse)::GetProcAddress(g_hInstDll,"StopHookMouse");    if( StopHook == NULL ){        SetDlgItemText(IDC_STATE,STATE2);    }    StopHook();    if(g_hInstDll != NULL){        ::FreeLibrary(g_hInstDll);    }

         

    • 置顶按钮,恢复按钮
      • 调用打开dll函数
      • 改变BOOL变量openORclose使OnMyMsg函数分别处理置顶还是恢复
      •  1 //启动置顶 2 BOOL openORclose = FALSE; 3 void CTopWndDlg::OnBnClickedOpen() 4 { 5     OpenHook(); 6     GetDlgItem(ID_OPEN)->EnableWindow(FALSE); 7     openORclose = TRUE; 8 } 9 10 //恢复置顶11 void CTopWndDlg::OnBnClickedClose()12 {13     OpenHook();14     GetDlgItem(ID_CLOSE)->EnableWindow(FALSE);15     openORclose = FALSE;16 }

         

    • 在消息处理函数中真正实现功能
      • 判断收到的鼠标事件是否是点击
      • 找到点击时鼠标所在的程序的句柄
      • 调用SetWindowPos函数使窗口置顶。参数1:目标程序窗口的句柄,参数2:(HWND_TOPMOST)置顶的参数,参数7:不改变窗口大小与位置
      • 处理结束,关闭与dll的连接
      •  1 //处理来钩子的信息,置顶与恢复的实现 2 LRESULT CTopWndDlg::OnMyMsg(WPARAM wParam,LPARAM lParam){ 3     CString str; 4     static PMSLLHOOKSTRUCT mouseHookStruct; 5     mouseHookStruct = (PMSLLHOOKSTRUCT)lParam; 6     if( wParam == WM_LBUTTONDOWN){ 7         HWND hWnd=::WindowFromPoint(mouseHookStruct->pt); 8         TCHAR title[MAX_PATH]; 9         ::GetWindowText(hWnd,title,MAX_PATH);10         if(openORclose){11             // HWND_TOPMOST 窗口置顶  SWP_NOMOVE | SWP_NOSIZE 不改变窗口大小和位置12             ::SetWindowPos( hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );13             GetDlgItem(ID_OPEN)->EnableWindow(TRUE);14             str.Format(_T("%s %s"),STATE3,title);15             SetDlgItemText(IDC_STATE, str);16         }17         else{18             ::SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );19             GetDlgItem(ID_CLOSE)->EnableWindow(TRUE);20             str.Format(_T("%s %s"),STATE4,title);21             SetDlgItemText(IDC_STATE,str);22         }23         CloseHook();24     }25     return 1;26 }
  5. 源码下载地址:C++手工实现topwnd源码
  6. 谢谢观赏~

 

TopWnd一键置顶窗口的实现,分享源码