消息处理函数的转移
//========================================================================
//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
轉載于:https://www.cnblogs.com/Jade2009/archive/2010/01/19/1651644.html
總結
- 上一篇: 网站应该更注重内部链接还是外部链接?
- 下一篇: VS插件的开发 - Visual Stu