当前位置:C++技术网 > 精选软件 > Windows零基础入门:2.11 修改窗口类实现文字的切换

Windows零基础入门:2.11 修改窗口类实现文字的切换

更新时间:2015-08-25 15:08:51浏览次数:1+次

    上一节课我们已经讲解了三种窗口类的情况,对此,你应该很清楚了。如果你没有清楚说明你没有看,那么请回去好好学习一下,然后再学习本节课。
    本节课讲解的是如何修改窗口类,也就是修改一个创建好的窗口类。本节课实现修改我们自己创建的窗口类,来达到闪烁的文字和窗口背景颜色的效果,让你深刻理解窗口类。
    下面是实现的效果图:
1.黑色窗口背景、红色文字背景和蓝色字
黑色窗口背景、红色文字背景和蓝色字
2.百色窗口背景、蓝色文字背景和红色字
百色窗口背景、蓝色文字背景和红色字
    我们上节课也说了,我们可以通过解除注册,也就是注销方式,把已经注册的窗口类删除。如果你还想用同一个类名,可以再注册一次。不过这样是不是过于麻烦了呢?所以,你肯定也想到了直接修改窗口类。
    注册窗口类就是增加一个窗口类信息,注销窗口类就是删除一个窗口类信息,而查询窗口类则在创建窗口时使用,那么修改已创建的窗口类就是本节课的内容了。至于具体的使用的解释,我们在下一节课讲解。
    各种信息的处理系统,无非就是增删改查用。没有其他的归类了,所以我们在研究窗口类时,同样也是这个套路。这样,我们就将窗口类的完整的知识体系就完成了。而绝大部分的课程和培训,基本没有做到这一点,不知道是他们研究不精,还是刻意将这些忽略,总之,对于我们这样喜欢钻研,喜欢把技术点研究个透彻的朋友来说,总是不完善。我们 C++技术网 以人为本的教学理念,所以普及编程,所以不急功近利的传授知识,更多是让你真正全面掌握这些知识,学会思考,学会学习。
    那么我们这节课好好讲讲修改窗口类。其实这个技术就是所谓的窗口子类化的概念,不过就是修改窗口类罢了。别人把这些东西搞得神乎其神,在我看来,不就是这个知识体系的一个小小部分而已。而绝大多数人学完Windows编程后,还不知道什么是窗口子类化,或者会用了,但是也不清楚到底是怎么回事,反正就是可以这样搞。知识没有一个完整的体系,或许他研究很久才会发现,原来就是这么回事!!
    在《Windows零基础入门:2.6 Win32第一个程序和计时文字闪烁》这一节课里,我们有一份完整的代码,你建立好Win32项目后,添加一个源文件cpp文件,然后粘贴这份代码,就可以运行起来。你可以好好看看这个代码和文章解释。
     我们第一个目标就是,修改自己创建的窗口类,然后才是修改系统窗口类。因为自己创建的窗口类过程完全在我们自己的把握之中,我们可以清晰的看到这个过程。先做讲解来理解这个过程。然后再来理解修改系统窗口类就轻松了。
    修改窗口类,系统已经提供了API函数SetWindowLong。它可以修改已经创建的窗口的风格、窗口过程、窗口ID和窗口关联的数据。这个函数的具体使用详解,如有必要,会单独讲解。
    修改的实现过程很简单。我们利用这个修改,可以随意切换窗口处理过程。只要修改一下窗口过程,窗口的消息就会发送到新的窗口过程中处理了。
    首先,准备好一个窗口过程。自己提供的窗口过程中,包含了另外一套消息处理。和原先的窗口过程一起,一共有两套了。
    然后通过使用SetWindowLong(hwnd, GWL_WNDPROC, (LONG)新窗口过程函数名),这样就可以重新设置了。SetWindowLong需要设置的窗口句柄,所以,你要等开始的窗口已经创建成功了,才能设置,不然你无法获取窗口句柄咯。你也可以等窗口创建出来后再给窗口类修改窗口过程,也可以创建窗口后,修改窗口类的窗口过程,然后再显示窗口。
    在创建窗口后显示窗口前修改窗口类,代码如下:

// - 创建窗口
hwnd = CreateWindow(szExeName, _T("我的窗口标题_C++技术网"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
// - 修改窗口类
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)MyProc);
// - 显示窗口
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);


    在创建窗口且显示窗口后修改窗口类,代码如下:

//-创建窗口
hwnd = CreateWindow(szExeName, _T("我的窗口标题_C++技术网"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
//-显示窗口
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
//- 修改窗口类
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)MyProc);


    这个区别不大,不必介意。不过先显示窗口,就可以在没有修改窗口类之前已经接受到消息了。所以,结合项目经验来说,一般都是创建窗口,就修改窗口类,然后才是显示窗口。不过这里只是一个示例而已,不必较真,知道区别即可。
    而窗口过程函数就和之前的一样,没有任何区别。当然你可以写另外的一套消息处理,这样一个窗口拥有两个处理过程,可以方便的实现不同的窗口样式等,而只需要切换一下窗口过程即可。这样是不是很有意思呢?你可以第二个窗口过程中的WM_PAINT中,显示另外的文字。而不需要使用对变量i取模2来实现闪烁了。不同的窗口过程分别显示一个信息,切换窗口过程后,也就执行新的一套窗口消息处理,这样也巧妙的实现了闪烁的效果。这个例子可以让你加深对窗口过程修改的理解。
    第一个窗口过程(修改窗口类指定的)的WM_PAINT代码如下:

hdc = BeginPaint(hwnd, &ps);// - 开始绘制
SetBkColor(hdc, RGB(255, 0, 0));// - 设置文字背景颜色
SetTextColor(hdc, RGB(0,0,255));// - 设置文字颜色
GetClientRect(hwnd, &rect);// -获取窗口客户区(显示区域)的大小
FillRect(GetWindowDC(hwnd), &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));//-绘制窗口背景颜色
DrawText(hdc, _T("Win32程序界面,自定义窗口过程"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);// - 绘制文字
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)WndProc);//- 切换窗口过程
swprintf(szTip, _T("计时:%d"), i);
DrawText(hdc, szTip, -1, &rect, DT_SINGLELINE | DT_CENTER);
EndPaint(hwnd, &ps);//-结束绘制
return 0;


   第二个窗口过程(注册窗口类时指定的)的WM_PAINT代码如下:

hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
SetBkColor(hdc, RGB(0, 0, 255));
SetTextColor(hdc, RGB(255, 0, 0));
FillRect(GetWindowDC(hwnd), &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
DrawText(hdc, _T("Win32程序界面,初始化窗口过程"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)MyProc);//- 切换窗口过程
swprintf(szTip, _T("计时:%d"), i);
DrawText(hdc, szTip, -1, &rect, DT_SINGLELINE | DT_CENTER);
EndPaint(hwnd, &ps);
return 0;


    如此就可以了。观察代码,你会发现,原先在一个窗口过程中,使用if(i%2)来间隔执行窗口显示的闪烁的,这里就没有了。代码中,有一个窗口过程切换的一句代码,就是完成闪烁的关键。下一节课,讲解修改系统窗口类的窗口过程,来定制控件的样式。