[百度空间] [原]MFC杂乱笔记

1.

创建动态菜单

假如ID是动态分配的,那么重载
virtual BOOLOnCmdMsg(UINT,int,void*,AFX_CMDHANDLERINFO*);

据MSDN不详细解释,当第二个参数值为CN_COMMAND时,是执行Command的消息,不过要看最后一个参数,如果最后一个参数为空,则为真正执行该命令.否则是查找是否有该命令ID的handler

BOOL TheWindow::OnCmdMsg(UINT nID,int nCode,void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo)
{

if( nCode == CN_COMMAND  )
    {
        if( nID >= BaseMenuID && nID < MaxMenuID )
        {
            if( pHandlerInfo == NULL )
            {
                //handle the Command nID here

}

return TRUE;

}

}

return ParentWnd::OnCmdMsg(nID,nCode,pExtra,pHandlerInfo);

}

根据MSDN,菜单的ID应该是全局的(貌似应该大于0x8000), 又根据WM_COMMAND消息格式,ID最好是一个WORD,ID如果超过一个WORD,例如0x10000,那么WM_COMMAND可以收到这个菜单的命令ID(但跟MSDN的描述LOWORD不一致,而是整个DWORD,这个可能是凑巧),但是MFC的OnCmdMsg只能收到更新消息(CN_UPDATE_COMMAND_UI),不能收到执行消息.

实时设置Menu的Enable和Disable状态(MF_ENABLED,MF_DISABLED,MF_GRAYED)为何无效?比如为何不能禁用菜单项?
在查了MSDN半天之后,终于在一个code example中看到了一段不起眼的注释:

// The code fragment below shows how to disable (and gray out) the
// File\New menu item.
// NOTE: m_bAutoMenuEnable is set to FALSE in the constructor of

// CMainFrame so no ON_UPDATE_COMMAND_UI or ON_COMMAND handlers are

// needed, and CMenu::EnableMenuItem() will work as expected.

大意就是说如果设置m_bAutoMenuEnable该标志为FALSE的话,EnableMenuItem()就可以正常使用了
没有设置该标志呢?猜测framework会自动更新菜单:根据消息映射检查菜单ID是否有handler,如果有,就将其激活,否则就禁用.所以每次手动设置之后就被自动改回来了....

2.

CMDIFrameWnd为何不能处理WM_KEYDOWN消息?(MFC9) 经研究发现,接受焦点的不是他本身,而是他的Client - m_hWndMDIClient,经测试GetFocus() 的返回值的HWND与m_hWndMDIClient的值一致.

因为焦点在他的客户区m_hWndMDIClient上,不在他自己身上,所以他自己无法接受WM_KEYDOWN等等.

3.

MFC DLL注意事项: 每次从外部调用,第一次进入MFC的DLL,都需要调用 AFX_MANAGE_STATE(::AfxGetStaticModuleState());

关于AFX_MANAGE_STATE,MSDN已经说得很清楚了:  Call this macro to protect an exported function in a DLL.

4.

如何在控件反射了自己的消息之后,还能让父窗口处理?答: ON_CONTROL_REFLECT_EX ,使用一个BOOL的返回值来确定是否让父窗口继续处理,TRUE表示让父窗口跳过该消息,FLASE则继续让父窗口处理.

ON_CONTROL_REFLECT 的消息处理函数返回值是void,即父窗口不能处理.但是这个消息会自动检查数据变化(如果数据没有变化,则不会调用该handler)

ON_CONTROL_REFLECT_EX 则不同,一旦控件被操作,就调用该handler,所以要手动检查数据.

ON_CONTROL_REFLECT_EX(CBN_SELCHANGE,&TheCombbox::OnSelectChange)

BOOL TheCombbox::OnSelectChange()
{
    //数据真的改变?
    {
        处理数据,返回FALSE ,通知父窗口
    }
    否则
    {
        返回TRUE,跳过
    }
}

暂时到这里.

时间: 2024-10-09 18:32:16

[百度空间] [原]MFC杂乱笔记的相关文章

[百度空间] [原]跨平台编程注意事项(三): window 到 android 的 移植

大的问题 先记录一下跨平台时需要注意的大方向. 1.OS和CPU 同一个操作系统, CPU也可能是不一样的, 比如windows也有基于arm CPU的版本,而android目前有x86,arm,mips几种. 即便是同一种CPU架构系列, 细节特性也不一样. 所以目前个人准备了3个宏开关来判断目标平台. OS, CPU, CPUbits OS对应不同的操作系统, CPU对应不同的CPU架构(比如x86和arm), CPU-bits目前是32和64, 比如CPU是x86时, CPUbits是64

[百度空间] [原]跨平台编程注意事项(一)

好久没有写东西了,先写一点,以后再扩充. 1.使用平台编译器预定义的宏.比如在windows下,有这样一个宏WIN32.或者_WIN32.linux下有__linux__等等. 比如OGRE的OgrePlatform.h中的定义: #if defined( __WIN32__ ) || defined( _WIN32 )#   define OGRE_PLATFORM OGRE_PLATFORM_WIN32 #elif defined( __APPLE_CC__)#   define OGRE_

[百度空间] [原]跨平台编程注意事项(二): windows下 x86到x64的移植

之前转的: 将程序移植到64位Windows 还有自己乱写的一篇: 跨平台编程注意事项(一) 之前对于x64平台的移植都是纸上谈兵,算是前期准备工作, 但起码在写代码时,已经非常注意了.所以现在移植起来相对很顺利.昨天用了一天时间把自己代码添加了x64支持.贴一下遇到的问题,就作为注意事项吧,以下文字来自我的cnblogs博客的另一文章,有修改 1.指针到数值的转换.  指针 (如void*)转到数值,要用intptr_t或者uintptr_t (用Win32的INT_PTR也可以,当然用C/C

[百度空间] [原] 全局operator delete重载到DLL

由于很久没有搞内存管理了,很多细节都忘记了今天项目要用到operator delete重载到DLL,发现了问题,网上搜索以后,再对比以前写的代码,发现了问题:原来MSVC默认的operator new(size_t) 和operator delete(void*)虽然可以重载, 但是不能封装到DLL中,编译会报C2375 DLL linkage错误,解决方法很简单: 用inline函数包一下DLL导出就可以了 同时为了不跟MFC等三方库的operator new 冲突,最好加一个自定义参数:ty

[百度空间] [原]android下的各种坑

一堆so文件安装不正确: apk里面都是全的, 但是安装完后/data/data/$pkg/lib下面就没有 google了好长时间没有结果.最后发现是因为没库有加lib前缀(当时想了一下觉得不加更好,更合胃口)....现在加上lib前缀OK了. 怀疑package manager在安装apk的时候把所有没有lib prefix的so给忽略了这种剧情设定太坑爹了.不使用官方mk真是吃尽苦头啊. ndk上坑太多: dlopen()还不支持RTLD_NODELETE,又得黑代码了. apk源的/li

[百度空间] [原]CImageList支持32位透明位图

32位的位图主要是包含Alpha值(0-255)可以有半透效果的.之前用FreeImage加载 的DIB, CImageList直接绘制会有黑色背景.即便用了ILC_MASK,也创建了mask map, 这种是旧式的图标/光标透明效果, 遮罩透明, 没有alpha通道和渐变,效果仍然很差.所以以前的toolbar/menu/tab control 都是ownerdraw, 先ExtractIcon,用DrawStat (DST_ICON)来绘制图标,这样绘的制是支持32位图标的.但是最近给too

[百度空间] [原]再谈静态变量的初始化顺序

有一段时间我被静态变量的初始化顺序搞的焦头烂额,因为我用了singleton的懒惰初始化(lazy initialization)方式,即不需要显式创建singleton,在getsignleton的时候自动创建,并且在最后销毁对象..比如singleton使用了内存分配对象,如果这个对象先于singleton析构(后于singleton构造),那么singleton析构的时候内存分配器已经不存在了.最后发现我忽略了effctive C++的条款47,看来很多细节还是不是很深入的领悟. 关于其中

[百度空间] [原]基于内存生命周期的内存管理

如果根据声明周期划分的话,内存可以大至划分为3类 1.静态内存 2.临时内存 3.普通内存 静态内存的特点是,程序开始(通常是初始化期间)分配的,而后就不会释放,直到程序结束,典型的如singleton,相信还有很多类,其实例只会被分配一次,而且理论上,生存期是贯穿整个程序的. 临时内存的特点通常如下: void function(){    ...    char* buffer = new char[size]; ... delete [] buffer;} 从上面可以看到,此种内存分配后,

[百度空间] [原]DLL导出实例化的模板类

因为模板是在编译的时候根据模板参数实例化的,实例化之后就像一个普通的类(函数),这样才有对应的二进制代码;否则,没有模板参数,那么编译器就不知道怎么生成代码,所以生成的DLL就没有办法导出模板了.但是根据MSDN的描述,可以导出模板类的实例化后的代码(注意:这里不是指实例化模板类的一个对象),比如 template<typename T> class singleton,那么可以导出singleton<MyClass>或者其他已知类型的类代码.详见: http://support.