使用DLL中的资源

我很早的时候写过一篇MFC中CDialog与其对话框资源的绑定,但这几天在MFC DLL上做了一些工作后发现当时的理解实在肤浅。说不定过了几年再回头看看目前这篇文章,又觉得本文也是鬼话连篇了吧,哈哈。 使用DLL中的资源面临的一个主要问题是,DLL和EXE中都有资源集,但是程序在运行态到底会去哪个资源集中找常常令我们疑惑。 考虑如下的经典情况: 在新建MFC DLL工程时选中Regular DLL using shared MFC DLL选项,新建一个与MFC自身DLL共享的DLL。在新DLL中新建一个ID名为IDD_DLLDIALOG的对话框资源。在这个DLL中导出一个ShowDialog()函数,内容如下: extern "C" void Show Dialog() { CDialog dlg(IDD_DLLDIALOG); dlg.Do...阅读全文

Effective c++ 札记2

1.=号运算符 1.1 尽量把=号运算符的返回值设定为一个当前对象的引用 1.2 要特别注意住在operator=中考虑处理自我赋值这一特例 1.3 复制时要复制所有成员,应特别注意当继承存在时的情况 2.资源管理 2.1   auto_ptr和shared_ptr的析构函数中只针对delete进行操作,而不是delete[],所以不要这样写 std::auto_ptr<std::string>  aps(new  std::string[10]) 2.2  为了解决上面的问题。可以使用 vector。或者,使用boost库中的boost::scoped_array、boost::shared_array 2.3  delete时注意是否要用delete[] ,这在有typedef时会是一个很隐蔽的陷阱 2.4  观察以下语句 processWidget(std::trl::shared ptr<Widget> (new  Widge...阅读全文

Effective c++ 札记1

1.空类? 当我们没有手动声明新的构造函数时,编译器会声明以下几个: 默认构造 拷贝构造 =号运算符 析构 惟有当这些函数被需要(被调用) ,它们才会被编译器创建出来。(这个以前还真不知道) 2.阻止上面的暗处的声明的方法 方法一:将其设为private(这样外部就无法访问),并且不写其定义(这样内部或友元也无法访问) 方法二:继承一个Uncopyable类 3.析构函数中的异常 c++类中的析构函数允许抛出异常,但这样做是极不受推荐的 如果有两个同类型的异常同时存在(这种情况在当类成员包含容器时会经常出现),那么程序若不是结束执行就很可能会导致不明确的行为 原则: 任何时候,析构函数都不要抛出异常,也尽量不要把可以抛出异常的...阅读全文

当你PostMessage到焦头烂额的时候

在各种 WM_ 间生活惯了, 仿佛离了PostMessage(),这份Google test就写不下去了。但是PostMessage() 的第一个句柄参数是个可恶的HWND,特别是当我想要发个键盘或是鼠标消息时,用spy++截了半天也找不到这天杀的消息到底是传到哪个HWND中了。这个时候,keybd_event 和 mouse_event可以帮上我们的大忙 其时,有时候翻翻windows的api,比起到处搜WM_能更快的解决问题。如果一个程序设计得足够好的话,它几乎可以完全通过keybd_event就能模拟所有的操作。在GUI层面上进行单元测试也就不必翻WM_翻得那么辛苦了。 嗯,就说这么多吧 阅读全文

堆调试利器-Pageheap

刚刚花了一个星期磨出一来一个Planet的*.prj类型的一周项目,感觉收获很大,特此作出分享. 此项目是要解决一个Heap Corruption的问题,但是我们知道,通常情况下,当我们在堆中分配了一段内存,尽管在使用过程中可能出现了越界操作,但是系统在越界的一瞬间常常并不直接报错,而是在最后delete 时抛出一个Heap Corruption。这是因为操作系统的堆分配粒度是一个4k,若内存越界不是刚好在那个4k边界上,并不会引起操作系统的警觉而报错。 如果我们只是在Heap Corruption发生的时候察看call stack,会发现得不到多少有用的信息。在一份规模较大的代码中手工检查也 不是很现实。 这个时候,堆调试利器-PageHeap可以帮上大忙.此工具可以强迫程序在把每...阅读全文

进一步理解C++中的堆(Heap)

最近的项目涉及到Heap Corruption的问题,所以对堆要有更深的理解。 进程初始化时会被分配一个默认大小为1M的默认堆,这个堆会被很多重要的函数调用,比如当我们调用ANSI版本的某些函数时,它们的Unicode版本字符串就会存于其中。若应用程序中有多个线程都用到了默认堆,那么会有机制使得同时只能有一线程能在默认堆中进行操作。默认堆的分配和销毁都是由系统控制的,但是我们可以通过GetPreocessHeap()来得到本进程的默认堆句柄。 常用的分配函数有VirtualAlloc和HeapAlloc.VirtualAlloc请求4K为边界的整块虚拟内存,HeapAlloc分配任意大小的内存块。但后者是依赖前者实现的。也就是说在操作系统的层面上管理内存的最小单位是4K。要实现更小的...阅读全文

CreateProcess诡异的参数问题

由于要写GTest的UI测试,要创建进程并向其发送消息。但是CreateProcess这个函数却一开始老是失败。 TEST(Clean_Up_Tests,Time_Table_Dlg ) { STARTUPINFO siStartInfo; PROCESS_INFORMATION piProcInfo; // Set up members of STARTUPINFO structure. siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.lpReserved = NULL; siStartInfo.lpReserved2 = NULL; siStartInfo.cbReserved2 = 0; siStartInfo.lpDesktop = NULL; siStartInfo.dwFlags = 0; //the cmdLine TCHAR szCmdLine[_MAX_PATH] = _T("Planet.exe"); int nCreateResult = CreateProcess(NULL, szCmdLine, NULL, NULL,FALSE, 0, N...阅读全文

大型程序多语言的两种实现思路

在国际化的程序中,经常要使用到语言切换的功能 以目前我正在做的为例,此程序有7种语言的切换功能 如此多的语言,为每一种语言单独设计一个对话框显然在大型程序中是不合适的 一般的,这会或多或少的利用dll.每个dll就是是个语言包。 为此,我所见的有两种设计思路: 1.语言包自带对话框资源 其实,其准确的说法是语言包自带对话框模版,因为这些dll工程中所引用的对话框都是完全相同的文件. 在写这些对话框时,他们的文本都只是一个宏名。对每一个宏名,不同的dll中对它有不同的define。 2.语言包只带自符串资源,对话框资源存在于主工程 在这种机制中,对话框资源中的文本显示的是什么已经不重要了,因为我们在加载对话框的时候可以分为两步...阅读全文

MFC中CDialog与其对话框资源的绑定

最近对于对话框选定资源的过程有了更进一步的了解 按一般的风格,MFC的对话框中一般都会有这么一行: enum { IDD = xxxxx }; 在这个对话框的构造函数里一般会这样写 InvoiceDialog::InvoiceDialog(CWnd* pParent /*=NULL*/) : CDialog(InvoiceDialog::IDD, pParent), m_Invoice(NULL) { //{{AFX_DATA_INIT(InvoiceDialog) // NOTE: the ClassWizard will add member initialization here //}}AFX_DAT _INIT theApp.ApplicationWindow()-&gt;m_pActiveHelpHandler=this; } 但是很多人可能都不明白,工程是怎么仅根据这一个IDD号就把一个CDialog绑定到一个对话框资源上 因为有时工程不止一个,资源也不止一处,IDE是如何选择资...阅读全文