zoukankan      html  css  js  c++  java
  • 消息处理函数的转移

    //========================================================================
    //TITLE:
    //    消息处理函数的转移
    //AUTHOR:
    //    norains
    //DATE:
    //    Wednesday  03-January-2008
    //Environment:
    //    VS2005 + SDK-WINCE5.0-MIPSII  
    //    EVC + SDK-WINCE5.0-MIPSII 
    //========================================================================

        Windows CE有一个很有意思的API函数,通过SetWindowLong函数可以转移原窗口的消息处理函数为自定义的.敏感的朋友估计一看见,就已经明白可以做什么了.呵呵,难道不是么?
       
       
    1.函数使用
     
        SetWindowLong的使用及其简单,比如我们将m_hEdWord窗口的消息处理函数置换为CtrlProc:

        SetWindowLong(m_hEdWord,GWL_WNDPROC,(DWORD)CtrlProc);
        就这么简单,现在只要m_hEdWord窗口收到消息,那么就会自动调用预先定义的CtrlProc.
     
        有设置,自然也有获取,不过这次我们是通过GetWindowLong函数:
        m_pPreProcEdWord = (WNDPROC)GetWindowLong(m_hEdWord,GWL_WNDPROC);
       现在m_pPreProcEdWord存储的就是目前m_hEdWord的消息处理函数地址.不过,其实通过SetWindowLong函数也能获取消息函数地址:
        m_pPreProcEdWord = SetWindowLong(m_hEdWord,GWL_WNDPROC,(DWORD)CtrlProc);
        不过这时候获取的却是在设置CtrlProc消息处理函数之前的函数地址.也就是说,这两段代码中m_pPreProcEdWord等价:
        1).
        m_pPreProcEdWord = SetWindowLong(m_hEdWord,GWL_WNDPROC,(DWORD)CtrlProc);
       
        2).
        m_pPreProcEdWord = (WNDPROC)GetWindowLong(m_hEdWord,GWL_WNDPROC);
        SetWindowLong(m_hEdWord,GWL_WNDPROC,(DWORD)CtrlProc);
        如果需要调用m_pPreProcEdWord指向的函数,则需要用上CallWindowProc:
        CallWindowProc(m_pPreProcEdWord,hWnd,wMsg,wParam,lParam);
       
    2.接管Windows Control消息
     
        说了一大堆似乎很有哲理的话,现在就让我们来看看有什么实际的作用吧.
       
        估计这个函数用得最多是在Windows Control中.比如,你想在Edit Box输入某个字符时做一些特殊处理,只能通过SetWindowLong来置换内部的处理函数进而调用自己的特殊处理函数.
       
        我们来举一个非常简单的例子,首先创建一个Edit Box控件,如果在该控件中按下键盘的"ESC",则会退出应用程序.为了方便突出问题的重点,我们的CMainWnd窗口继承于CWndBase(关于CWndBase请见:http://blog.csdn.net/norains/archive/2007/11/10/1878218.aspx)

    #pragma once
    #include "wndbase.h"

    class CMainWnd :
        public CWndBase
    {
    public:
        CMainWnd(void);
        ~CMainWnd(void);
        BOOL Create(HINSTANCE hInst, HWND hWndParent, const TCHAR *pcszWndClass, const TCHAR *pcszWndName);

    protected:   
        static LRESULT CtrlProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);

    private:
        HWND m_hEdWord; //The window is for inputing the word
        WNDPROC m_pPreProcEdWord; //Pointer to the previous window procedure for the input word window.
    };

    #include "stdafx.h"
    #include "MainWnd.h"

    //---------------------------------------------------------------------------------------
    //Default value
    #define IDC_EDIT_WORD        101


    //////////////////////////////////////////////////////////////////////
    // Construction/Destruction
    //////////////////////////////////////////////////////////////////////
    CMainWnd::CMainWnd(void)
    {
    }

    CMainWnd::~CMainWnd(void)
    {
    }


    //----------------------------------------------------------------------
    //Description:
    //    Create the window. It's override function
    //
    //----------------------------------------------------------------------
    BOOL CMainWnd::Create(HINSTANCE hInst, HWND hWndParent, const TCHAR *pcszWndClass, const TCHAR *pcszWndName)
    {
        if(CWndBase::Create(hInst, hWndParent, pcszWndClass, pcszWndName) == FALSE)
        {
            return FALSE;
        }

        //The edit window for input the word
        m_hEdWord = CreateWindowEx(WS_EX_TOPMOST,
                                    TEXT("EDIT"),
                                    TEXT(""),
                                    ES_LEFT  | WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_BORDER,
                                    GetSystemMetrics(SM_CXSCREEN) / 3,
                                    GetSystemMetrics(SM_CYSCREEN) / 3,
                                    GetSystemMetrics(SM_CXSCREEN) / 3,
                                    GetSystemMetrics(SM_CYSCREEN) / 3,
                                    m_hWnd,
                                    (HMENU)IDC_EDIT_WORD,
                                    m_hInst,
                                    NULL);

        //Store the pointer in the window
        SetWindowLong(m_hEdWord, GWL_USERDATA, (DWORD)this);
        //Get the previous window procedure
        m_pPreProcEdWord = (WNDPROC)GetWindowLong(m_hEdWord,GWL_WNDPROC);
        //Set the new window procedure
        SetWindowLong(m_hEdWord,GWL_WNDPROC,(DWORD)CtrlProc);

        return TRUE;
    }


    //----------------------------------------------------------------------
    //Description:
    //    Windows control process.
    //
    //----------------------------------------------------------------------
    LRESULT CMainWnd::CtrlProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
    {
        CMainWnd *pObject = (CMainWnd *)GetWindowLong(hWnd,GWL_USERDATA);

        if(pObject->m_hEdWord == hWnd)
        {
            switch(wMsg)
            {
                case WM_CHAR:
                {
                    if((TCHAR) wParam == VK_ESCAPE)
                    {
                        PostQuitMessage(0x00);
                    }
                    break;
                }
            }
            return CallWindowProc(pObject->m_pPreProcEdWord,hWnd,wMsg,wParam,lParam);
        }

       
        //It should never get here !
        return DefWindowProc(hWnd,wMsg,wParam,lParam);
    }

        程序代码段很短,但有几点需要注意的地方.
       
        CtrlProc是我们用来置换原有过程的消息处理函数,因为CtrlProc为静态才能回调,而静态函数无法调用成员变量,所以我们在创建Edit Box实例之后在GWL_USERDATA地址存储了当前对象指针:


        SetWindowLong(m_hEdWord, GWL_USERDATA, (DWORD)this);
        然后在CtrlProc函数中获取存储在GWL_USERDATA中的对象指针,用该指针调用成员变量及函数:

        CMainWnd *pObject = (CMainWnd *)GetWindowLong(hWnd,GWL_USERDATA);
        因为我们只是处理WM_CHAR消息,其它消息都采用默认处理方式,所以直接返回调用先前的消息函数:

     return CallWindowProc(pObject->m_pPreProcEdWord,hWnd,wMsg,wParam,lParam);
       这个例子很简单,该工程可以在此下载:http://download.csdn.net/source/324833


    3.系统必崩溃代码

        如果将消息处理函数处理转移到已经释放的内存上,那么会有什么结果呢?结果就是,系统崩溃!有兴趣的朋友可以试试这段代码:


    LRESULT MyProc(HWND hWnd, UINT wMsg,WPARAM wParam, LPARAM lParam)
    {
        return DefWindowProc(hWnd,wMsg,wParam,lParam);
    }

    int WINAPI WinMain(    HINSTANCE hInstance,
                        HINSTANCE hPrevInstance,
                        LPTSTR    lpCmdLine,
                        int       nCmdShow)
    {
         // TODO: Place code here.

        HWND hWnd = GetForegroundWindow();
        SetWindowLong(hWnd,GWL_WNDPROC,(DWORD)MyProc);
        return 0;
    }

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/norains/archive/2008/01/03/2023986.aspx

  • 相关阅读:
    组装query,query汇总,query字段
    POJ 1276, Cash Machine
    POJ 1129, Channel Allocation
    POJ 2531, Network Saboteur
    POJ 1837, Balance
    POJ 3278, Catch That Cow
    POJ 2676, Sudoku
    POJ 3126, Prime Path
    POJ 3414, Pots
    POJ 1426, Find The Multiple
  • 原文地址:https://www.cnblogs.com/Jade2009/p/1651644.html
Copyright © 2011-2022 走看看