zoukankan      html  css  js  c++  java
  • 控件给父窗口的消息

       一、 创建自定义控件的窗口类

        利用Visual C++6.0集成开发环境创建一个名为Ryg的正规的动态连接库。在Ryg.cpp中,加入

    extern"C" __declspec(dllexport)void RygEntry(){}

        此虚构的导出RygEntry 函数只是为了DLL能被隐式连接。客户必须包括对该函数的调用,而且调用必须在程序的执行路径里,否则编 译器会忽略该调用。作为选择,客户程序也可以在其InitInstance 函数中调用Win32的LoadLibrary函数,这样可显示连接该 DLL。 在Ryg.cpp 中加入

    CRygWnd::RegisterWndClass(AfxGetInstanceHandle());

    此函数注册一个窗口。

        现在编制CRygWnd类,在Insert菜单下选择New Class...子菜单,然后创建一个CWnd的派生类CRygWnd类,打开RygWnd.h文件,增加如下内容:

    class CRygWnd : public CWnd

    {

    .........

    public:

    static BOOL RegisterWndClass(HINSTANCE hInstance);

    .........

    };

    在RygWnd.h中声明了RegisterWndClass函数,现在打开RygWnd.cpp文件,在此文件中编写此函数如下:

    BOOL CRygWnd::RegisterWndClass(HINSTANCE hInstance)

    { WNDCLASS wc; wc.lpszClassName = "RYG"; wc.hInstance = hInstance; wc.lpfnWndProc = RygWndProc; wc.hCursor = ::LoadCursor(NULL,IDC_ARROW); wc.hIcon = 0; wc.lpszMenuName = NULL; wc.hbrBackground = (HBRUSH) ::GetStockObject(LTGRAY_BRUSH); wc.style = CS_GLOBALCLASS; wc.cbClsExtra = 0; wc.cbWndExtra = 0; return (::RegisterClass(&wc) != 0);

    }

        在函数RegisterWndClass中,首先是构造一个窗口类结构WNDCLASS ,然后,用窗口注册函数 RegisterClass对此窗口注册。对话框资源板利用符号化的窗口类名来指定自定义控件RYG(如图一所示)。在此函数中,最重要的是类名 lpszClassName和指向WNDPROC函数的指针 lpfnWndProc 。在构造好WNDCLASS类结构后,函数 RegisterClass把该结构拷贝到进程内存,进程中的任何函数都可以用该类创建窗口。当对话框被初始化时,Windows根据保存在模板里的窗口 类名,创建自定义控件子窗口。

    图 一

        二、 编制Windows过程处理函数WndProc

        在掌握了注册一个窗口类名后,下面要做的是如何编制一个Windows过程WndProc。过程WndProc主要是处理自定义控件窗口 消息,它是自定义窗口与类CRygWnd建立连接的桥梁。为了完成这个工作,首先,我们必须用new构造一个C++类目标,然后,告诉Windows把自 定义控件窗口中的所有消息送到C++类目标,当第一个消息WM_NCCREATE到达时,句柄hWnd为空,因此必须先用new构造一个C++类。下面是 WndProc函数的具体内容。

    LRESULT CALLBACK AFX_EXPORT RygWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)

    { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CWnd* pWnd; pWnd = CWnd::FromHandlePermanent(hWnd); if(pWnd == NULL){ pWnd = new CRygWnd(); pWnd->Attach(hWnd); } ASSERT(pWnd->m_hWnd == hWnd); ASSERT(pWnd == CWnd::FromHandlePermanent(hWnd)); LRESULT lResult = AfxCallWndProc(pWnd,hWnd,message,wParam,lParam); return lResult;

    }

        当对话框管理者构造一个对话框时,它为对话框里的每一个控件依据其类名调用:CreateWindow,因为我们已经为交通灯注册了类名 RYG,并且告诉Windows送所有的消息到RygWndProc,所以,当对话框管理者创建交通灯控件时,RygWndProc将接收到消息 WM_NCCREATE并构造一个C++类RygWnd。以后所有其他消息将送到AfxCallWndProc。

        三、 自定义控件的窗口消息

        控件窗口与C++类CRygWnd建立起连接后,下面要做的是如何响应窗口消息。控件通过给父窗口发送特定的WM_COMMAND窗口消息与父窗口进行通讯。控件以下面的方式发送窗口消息:

    GetParent()->SendMessage(WM_COMMAND,GetDlgCtrlID() | ID_NOTIFYCODE, (LONG)GetSafeHwnd());

    在客户方,可以用MFC的ON_CONTROL宏映射消息,如下所示:

    ON_CONTROL(ID_NOTIFYCODE,ID_MYCONTROL,OnClickedMyControl)

    在此应充分理解SendMessage函数,SendMessage函数原型是:

    LRESULT SendMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 )

    其中,message是指需要发送的消息,可以是WM_COMMAND,WM_HVSCROLL等消息,wParam和lParam参数是一个32位的附加依赖信息,wParam的高16位为通知码,wParam的低16位为子窗口ID,lParam为子窗口句柄。

        下面创建一个左鼠标按下事件:

    void CRygWnd::OnLButtonDown(UINT nFlags, CPoint point)

    {GetParent()->SendMessage(WM_COMMAND,GetDlgCtrlID() | 0, (LONG)GetSafeHwnd()); CWnd::OnLButtonDown(nFlags, point);

    }

    通过以上步骤就建立了一个自定义控件RYG的框架,然后,我们可以写设置背景色、三个交通灯等函数,这样一个自定义控件就圆满完成了。

        四、 在程序中使用自定义控件DLL

        以上是自定义控件DLL编程,下面是客户程序如何应用此自定义控件DLL的例子。首先,用对话框编辑器创建一个IDD_RYGTEMP模板,在控件窗口里,选择自定义控件,然后,在模板里画一个自定义窗口ID_RYG,如图二所示:


    图 二

        指定自定义窗口类名为RYG(如图一),然后用ClassWizard生产CDialog派生的类CRygDialog。其次,在 RygDialog.cpp文件中编辑构造函数,加入RygEntry()函数,初始化数据成员。最后,映射控件的左按键窗口消息,在 RygDialog.cpp文件里加入消息映射入口和控制函数:

    ON_CONTROL(0,IDR_RYG,OnClickRyg)

    在上面的OnLButtonDown 函数中的SendMessage定义了通知码0,因此,在ON_CONTROL函数中相应的用0通知码。
  • 相关阅读:
    [原创]桓泽学音频编解码(13):AC3 位分配模块算法分析
    白话红黑树系列之一——初识红黑树
    白话红黑树系列之二——红黑树的构建
    数据驱动编程之表驱动法
    每周一算法之六——KMP字符串匹配算法
    HDOJ 1098 Ignatius's puzzle
    HDOJ 1097 A hard puzzle(循环问题)
    HDOJ 1019 Least Common Multiple(最小公倍数问题)
    辗转相除法_欧几里得算法_java的实现(求最大公约数)
    HDOJ 1020 Encoding
  • 原文地址:https://www.cnblogs.com/cplusplus/p/2160426.html
Copyright © 2011-2022 走看看