zoukankan      html  css  js  c++  java
  • MFC自绘皮肤编写[笔记一] .

    用了这么长时间的MFC,感觉不错是不错,可是那个界面呀,真让人难受啊.虽然在VS2008中有了提供,但是还是不理想,所以就想找个皮肤库,现在比较好用的(个人感觉)SkinMagic,不过它不支持VS2008悲哀呀.所以打算自己写一个.

    关于那些基础知识和HOOK的知识我就不详细说了,可以去

    http://www.fengfly.com/plus/view-171863-1.html

    这里来看下.虽然这个是用C#但还是让我收获不小

    我们现在采用在要HOOK方式来给界面换肤,下面就来说一具体的步骤,

    这里用到的是VS2008,不采用VC 6.0这样就可以直接要VS 2008中使用了.由于也可以让别人来使用,所以我们就用DLL的方式来换肤.



    具体步骤:

    1.新建一个Dll工程,这里我命名的是"dll",选择"带静态链接 MFC 的规则 DLL(R)",然后完成

    2.打开工程的主要cpp文件,我的是dll.cpp.然后添加一个RunHook函数

    1. /******************************************************************** 
    2. 函数名称:       安装钩子 
    3. ===================================================================== 
    4. 参数说明:       dwThreadID当前进程的ID,hModule默认方式0 
    5. --------------------------------------------------------------------- 
    6. 文件作者:       King.Sollyu 
    7. *********************************************************************/  
    8. HHOOK  hWndHook ;   //全局变量   
    9. HINSTANCE hMod = NULL;  
    10. BOOL __stdcall RunHook( DWORD dwThreadID, HMODULE hModule = 0)  
    11. {  
    12.     hWndHook = SetWindowsHookEx(  
    13.         WH_CALLWNDPROC, (HOOKPROC) HOOKProc, hMod , dwThreadID );  
    14.     return TRUE;  
    15. }  

     这个函数是我们的主要函数,它是我们的主入口,下面来看一下 HOOKProc 为个钩子函数

     

    1. /******************************************************************** 
    2. 函数名称:       定义钩子函数 
    3. ===================================================================== 
    4. 参数说明:       无 
    5. --------------------------------------------------------------------- 
    6. 文件作者:       King.Sollyu 
    7. *********************************************************************/  
    8. LRESULT CALLBACK HOOKProc( int nCode, WPARAM wParam, LPARAM lParam )  
    9. {  
    10.     PCWPSTRUCT  wc = (PCWPSTRUCT) lParam;  
    11.     HWND  hWnd = wc->hwnd;  
    12.     if( hWnd )   
    13.     {  
    14.         wchar_t ClassName[MAX_PATH] =_T("");  
    15.   
    16.         GetClassName( hWnd, ClassName, MAX_PATH );  
    17.   
    18.         CWnd    *pWnd = CWnd::FromHandle( hWnd );  
    19.   
    20.         if (wcscmp( ClassName, _T("Edit") ) == 0)   //修改编辑框的窗口函数   
    21.         {  
    22.             CWnd    *pWnd = CWnd::FromHandle( hWnd );  
    23.   
    24.             pWnd->ModifyStyleEx(WS_EX_CLIENTEDGE,0,0);   //取消编辑框的边框   
    25.   
    26.             WNDPROC WndProc;  
    27.             WndProc = (WNDPROC) GetWindowLong( hWnd, GWL_WNDPROC );  
    28.   
    29.             CDrawEdit *pEdit=(CDrawEdit*)GetWindowLong(hWnd,GWL_USERDATA);  
    30.   
    31.             if (pEdit != NULL&& pEdit->m_Flag==1 )  
    32.             {  
    33.                 SetWindowLong(hWnd, GWL_USERDATA, 0);  
    34.                 SetWindowLong( hWnd, GWL_WNDPROC, (LONG)pEdit->m_OldProc);  
    35.   
    36.                 pEdit->m_OldProc = NULL;  
    37.                 delete pEdit;  
    38.             }  
    39.             else if (pEdit == NULL )   
    40.             {  
    41.                 if( WndProc !=EditWindowProc )  
    42.                 {  
    43.                     pEdit = new CDrawEdit();  
    44.                     pEdit->m_OldProc = WndProc;  
    45.                     SetWindowLong(hWnd,GWL_USERDATA,(long)pEdit);  
    46.                     WndProc =  (WNDPROC) SetWindowLong( hWnd, GWL_WNDPROC, (LONG) EditWindowProc);  
    47.                 }  
    48.             }         
    49.         }  
    50.     }  
    51.         return CallNextHookEx( hWndHook, nCode, wParam, lParam );  
    52. }  

     这样我们会发现CDrawEdit这个是这个错误.CDrawEdit是我们自定义的一个Edit类,它的主要功能是实现自绘Edit框.下面是CDrawEdit在代码

    1. /******************************************************************** 
    2. 函数名称:       定义编辑框类 
    3. ===================================================================== 
    4. 参数说明:       无 
    5. --------------------------------------------------------------------- 
    6. 文件作者:       King.Sollyu 
    7. *********************************************************************/  
    8. class CDrawEdit  
    9. {  
    10. public:  
    11.     WNDPROC     m_OldProc;         //记录编辑框的窗口函数   
    12.     int         m_Flag;   
    13. public:  
    14.     CDrawEdit()  
    15.     {  
    16.         m_OldProc = NULL;  
    17.         m_Flag    = 0;  
    18.     }  
    19.     HBRUSH CtlColor(HWND hWnd,HDC hDC, UINT nCtlColor)  
    20.     {  
    21.         CDC* dc = CDC::FromHandle(hDC);     //获取画布对象   
    22.         CRect rect;  
    23.         ::GetClientRect(hWnd,rect);         //获取客户区域   
    24.         rect.InflateRect(1,1,1,1);          //将客户区域增大一个像素   
    25.         CPen pen(PS_SOLID,1,RGB(0,255,0));  //创建画笔   
    26.         dc->SelectObject(&pen);  
    27.         CBrush brush (RGB(0,255,0));        //创建画刷   
    28.         dc->FrameRect(rect,&brush);          //绘制边框   
    29.         return brush;  
    30.     }  
    31. };  
    32.   
    33. /******************************************************************** 
    34. 函数名称:       编辑框窗口函数 
    35. ===================================================================== 
    36. 参数说明:       无 
    37. --------------------------------------------------------------------- 
    38. 文件作者:       King.Sollyu 
    39. *********************************************************************/  
    40. LRESULT __stdcall EditWindowProc(HWND hWnd,UINT Msg,WPARAM wParam,   
    41.                                  LPARAM lParam )  
    42. {  
    43.     CPoint pt;  
    44.     CDrawEdit *pEdit=(CDrawEdit*)GetWindowLong(hWnd,GWL_USERDATA);  
    45.     switch (Msg)  
    46.     {  
    47.     case WM_PAINT:   
    48.         {  
    49.             pEdit->CtlColor(hWnd,::GetDC(hWnd),0);  
    50.             break;  
    51.         }  
    52.   
    53.     case WM_DESTROY:  
    54.         {                 
    55.             WNDPROC procOld=pEdit->m_OldProc;  
    56.             SetWindowLong(hWnd,GWL_WNDPROC,(long)procOld); //恢复原来的窗口函数   
    57.   
    58.             CWnd* pWnd = ::CWnd::FromHandle(hWnd);          //将按钮对象与句柄分离   
    59.             if (pWnd)  
    60.             {  
    61.                 pWnd->Detach();  
    62.             }  
    63.             pEdit->m_Flag = 1;  
    64.             return 1;  
    65.         }  
    66.     default :  
    67.         {  
    68.   
    69.             break;  
    70.         }  
    71.     }  
    72.     return CallWindowProc(pEdit->m_OldProc, hWnd, Msg, wParam, lParam );  
    73. }  

     把必要的函数在头文件中声明下,或者放在RunHook 这个函数之前.

    添加卸载钩子函数

    1. /******************************************************************** 
    2. 函数名称:       卸载钩子 
    3. ===================================================================== 
    4. 参数说明:       无 
    5. --------------------------------------------------------------------- 
    6. 文件作者:       King.Sollyu 
    7. *********************************************************************/  
    8. BOOL __stdcall StopHook()  
    9. {  
    10.     UnhookWindowsHookEx(hWndHook);  
    11.     return TRUE;      
    12. }  

    3.导出函数

    打开dll.def,在下面添加

     RunHook
     StopHook

    下面是整个dll.def的内容

    1. ; dll.def : 声明 DLL 的模块参数。  
    2.   
    3. LIBRARY      "dll"  
    4.   
    5. EXPORTS  
    6.     ; 此处可以是显式导出  
    7.     RunHook  
    8.     StopHook  

    然后编译一下.本人测试通过


    这样我们就可以实现所有的"编辑框"的换肤.现在再新建一个exe工程来测试一下我们dll是不是可以正常的使用

    1.新建一个exe工程添加到当前的工程中.这里我选的是"基于对话框(D)"和" " .其它默认

    2.在对话框中添加一个"编辑框"

    3.在exeApp.cpp中包含dll.h和使用隐式连接dll.lib,

    1. #include "../dll/dll.h"  
    2. #pragma comment(lib,"../debug/dll.lib")  

    并在InitInstance函数中添加代码

    1. RunHook(GetCurrentThreadId());  

    编译一下,本人用win 7旗舰版+VS 2008编译通过

    下面是程序的运行截图

     

  • 相关阅读:
    win8系统下,python 2.7安装xlrd,xlutils和xlwt的方法
    phone number
    string to int
    Linux P2V Azure
    Azure IaaS 知识点小节
    Exchange端口列表
    自签名证书和私有CA签名的证书的区别 创建自签名证书 创建私有CA 证书类型 证书扩展名(转)
    Power BI REST API
    Web App 压力测试
    Azure IaaS限制
  • 原文地址:https://www.cnblogs.com/jinsedemaitian/p/5589123.html
Copyright © 2011-2022 走看看