对话框2

对话框是窗口,那么窗口背后一定有一个窗口类,而这个类的名称是#32770
现在有这种情况:如果应用程序是基于对话框的,那么一定还要很多对话框,而我又想改变对话框的类,
可是牵一发而动全身,所有的对话框都变了,那么要修改默认的对话框类名#32770,如何做呢?

想想在注册类时可以给出类名,但那是我自己设计的类阿,而对话框类是M$设计的阿,麻烦!
且慢,M$也一定用RegisteClassEx来注册的,那么RegisterClassEx做了什么呢?
让win95-a-developers-guide(第一章)来告诉我们吧!
1.检验类别的名称,如果该名被同一个exe或dll注册了,则传回INVALID_ATOM
2.如果类别的style被指定为CS_GLOBALCLASS,系统在检验类别名称时,发现它已被这个进程空间中的任何exe或dll注册(进程空间中不一定只有一个exe(文件本身)),那么传回INVALID_ATOM
3.配置内存用来存储类别的内容
4.将WNDCLASSEX结构中的内容复制到3配置的内存,并设定额外位为0
5.配置一块内存用来存放类别的中菜单的名称,lpszMenuName将指向该内存
6.将类别的名称加进系统的local atom table中,并将atom值存入类别的内存中
7.传回atom值

也就是说,自己注册的类别不能有CS_GLOBALCLASS属性或类别已经被注册了!

上面唯一不懂的是CS_GLOBALCLASS(local atom table除外),下面介绍他:
CS_GLOBALCLASS属于类别的范围
系统中许多程序注册窗口类别,许多dll也注册窗口类别,那么系统如何组织这些类别的呢?
在win32中要求一个进程对他将要产生的窗口,注册窗口类别。一个程序不能代替另一个程序注册窗口类别,也不能产生一个根据其他程序所注册的窗口类别而产生窗口(这里说明了为什么对话框类在dll中,如果在exe中,那么别的程序就要设计自己的对话框类了--那可是一件累事)

总之,注册好的窗口类别只能在一个进程中使用,不能跨进程使用
在每个进程中窗口类别可有3种不同的类别:module local,process global,system global
exe,dll都可以注册module local类别,并供自己使用!
例如:
同一进程中有exe 和一个dll,代码如下
int WINAPI WinMain(HINSTANCE hinstExe,HINSTNCE hinstExePrev,...)
{
WNDCLASSEX wc;
wc.lpszClassName = "Exe-registered WndClass";
wc.hInstance = hInstExe;  //exe is the registrant 说明类别是谁注册的,用来区别是module local
         process global..
..
RegisterClassEx(&wc);
return 0;
}

HWND DllCreateAnExeWindow()
{
return(CreateWindowEx(0,"Exe-registered WndClass",...,g_hinstDll,...));
}

DllCreateAnExeWindow永远不会成功,他会传回NULL,为什么?就是这个窗口类别被exe注册,其HINSTANCE是WinMain的参数.当DllCreateAnExeWindow他会收到正确的类别名称,然而在收到的HINSTANCE是Dll的,
那么在CreateWindowsEx时系统比较类别名称,同时也比较类别的注册者(也就是wc.hInstance)和窗口的产生者(CreateWindowsEx(...,hInstance...)),如果匹配就产生窗口

所以有什么方法可以在dll中产生由exe注册的类别的窗口实例,或者有什么方法在exe中产生由dll注册的类别的窗口实例.
有两种方法:
1.使得HINSTANCE的值匹配
HWND DllCreateAnExeWindow()
{
HINSTANCE hinstExe = GetModuleHandle(NULL);
return(CreateWindowEx(0,"Exe-registered WndClass",...,hinstExe,...));
}
但是我们无法在exe中取得dll的HINSTANCE,dll属于被加载的INSTANCE,取也取到的是加载dll的HINSTANCE!
解决方法是不要比较HINSTANCE

只要在这个进程中的都可以用!
如何做到dll中注册的类别能让exe使用呢?
dll在被加载时,会调用DllMain(也就是我们自己的dll), 我们让DllMain为dll所提供的每一个窗口类别调用RegisterClassEx,之后程序便可以调用CreateWindowEx来产生这些窗口类别的实例,
new common controls (如tree listbox)都是由ComCtl32.dll提供的
为什么会这要呢?那里体现不要匹配HINSTANCE呢?别急,听我谩慢道来,
ComCtl32.dll在调用RegisterClassEx之前他会为ComCtl32.dll提供的类别中的CS_GLOBALCLASS属性打开,当系统看到类别是以CS_CLOBALCLASS类型来注册时,会以Process Global级别来看待类别的,从而不需要匹配HINSTANCE了!
那么对话框的窗口类结构中的stlye也一定有CS_GLOBALCLASS属性,我们只要取得对话框类的属性,
将CS_GLOBALCLASS去掉,并给与新的类别名,就能改变对话框类的名称了,妙阿!哈哈

如何取得类别的属性呢?
GetClassInfoEx(hinst,lpszClassname,PWNDCLASSEX pwc);

那么改变对话框类的代码如下:
void ChangeDialogClassName(TCHAR szNewName[])
{
WNDCLASSEX wc;
GetClassInfoEx(NULL,"#32770",&wc)
//修改wc
wc.style &= ~CS_GLOBALCLASS  //自己注册的类别不能有CS_GLOBALCLASS
wc.lpszClassName = szNewName;
RegisterClassEx(&wc);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值