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

  • 相关阅读:
    监考
    初步确定五一粤东出行计划
    煤矿粉尘监控系统中心站软件3层设计
    c# 程序调用代码生成数据库
    Socket 一个服务器监听多个客户端 功能实现
    软件开发进度表
    sql server日期时间格式转换字符串简介
    Sql建表和sql语句的注意事项
    分布式设计与开发(一)宏观概述
    分布式设计与开发(四)数据拆分
  • 原文地址:https://www.cnblogs.com/Jade2009/p/1651644.html
Copyright © 2011-2022 走看看