消息处理函数的转移

//========================================================================
//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.youkuaiyun.com/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.youkuaiyun.com/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;
}

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/norains/archive/2008/01/03/2023986.aspx

转载于:https://www.cnblogs.com/Jade2009/archive/2010/01/19/1651644.html

【SCI复现】含可再生能源与储能的区域微电网最优运行:应对不确定性的解鲁棒性与非预见性研究(Matlab代码实现)内容概要:本文围绕含可再生能源与储能的区域微电网最优运行展开研究,重点探讨应对不确定性的解鲁棒性与非预见性策略,通过Matlab代码实现SCI论文复现。研究涵盖多阶段鲁棒调度模型、机会约束规划、需求响应机制及储能系统优化配置,结合风电、光伏等可再生能源出力的不确定性建模,提出兼顾系统经济性与鲁棒性的优化运行方案。文中详细展示了模型构建、算法设计(如C&CG算法、大M法)及仿真验证全过程,适用于微电网能量管理、电力系统优化调度等领域的科研与工程实践。; 适合人群:具备一定电力系统、优化理论和Matlab编程基础的研究生、科研人员及从事微电网、能源管理相关工作的工程技术人员。; 使用场景及目标:①复现SCI级微电网鲁棒优化研究成果,掌握应对风光负荷不确定性的建模与求解方法;②深入理解两阶段鲁棒优化、分布鲁棒优化、机会约束规划等先进优化方法在能源系统中的实际应用;③为撰写高水平学术论文或开展相关课题研究提供代码参考和技术支持。; 阅读建议:建议读者结合文档提供的Matlab代码逐模块学习,重点关注不确定性建模、鲁棒优化模型构建与求解流程,并尝试在不同场景下调试与扩展代码,以深化对微电网优化运行机制的理解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值