程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> .NET實例教程 >> 消息處理函數的轉移

消息處理函數的轉移

編輯:.NET實例教程

//========================================================================
//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,

$False$

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);

R: #0000ff">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

LOR: #808080">//////////////////////////////////////////////////////////////////////
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 n>= (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;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved