跟我一起玩Win32开发(3):窗口的重绘
c可以编译
#include <Windows.h> //先声明一下消息处理函数
LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); // 入口点
int CALLBACK WinMain(
HINSTANCE hInstance,
HINSTANCE hPrvInstance,
LPSTR lpCommandLine,
int cmdShow)
{
CHAR* cln = "MyApp";
//设计窗口类
WNDCLASS wc = {};
wc.hInstance = hInstance;
wc.lpszClassName = cln;
wc.lpfnWndProc = MyWindowProc;
//注册窗口类
RegisterClass(&wc);
// 创建窗口
HWND hMainwind = CreateWindow(
cln,
"绘制窗口",
WS_OVERLAPPEDWINDOW,
20,
12,
450,
300,
NULL,
NULL,
hInstance,
NULL);
// 显示窗口
if(hMainwind == NULL)
return 0;
ShowWindow(hMainwind,SW_NORMAL);
// 消息循环
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
} // 窗口消息处理程序
LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_PAINT:
break;
case WM_DESTROY:
PostQuitMessage(0);//退出程序
return 0;
default:
return DefWindowProc(hwnd,msg,wParam,lParam);
}
}
上面这段是修改了char不兼容,蓝色地方 宽字符
c/c++都可以编译 #include <Windows.h>
#include<iostream>
//先声明一下消息处理函数
LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); // 入口点
int CALLBACK WinMain(
HINSTANCE hInstance,
HINSTANCE hPrvInstance,
LPSTR lpCommandLine,
int cmdShow)
{
//PCWSTR cln = 0;
//设计窗口类
WNDCLASS wc = { 0 };
wc.hInstance = hInstance;
wc.lpszClassName = "ewfewew";
wc.lpfnWndProc = MyWindowProc;
//注册窗口类
RegisterClass(&wc);
// 创建窗口
HWND hMainwind = CreateWindow(
"ewfewew",
"qwer",
WS_OVERLAPPEDWINDOW,
20,
12,
450,
300,
NULL,
NULL,
hInstance,
NULL);
// 显示窗口
if (hMainwind == NULL)
return 0;
ShowWindow(hMainwind, SW_NORMAL);
// 消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
} // 窗口消息处理程序
LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_PAINT:
break;
case WM_DESTROY:
PostQuitMessage(0);//退出程序
return 0;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
} }
我们今天来吹一下关于窗口重绘的事情,在开始吹牛之前,我们先用上一篇博文中说到的方法写一个简单的Win32应用程序。代码如下:
- #include <Windows.h>
- //先声明一下消息处理函数
- LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
- // 入口点
- int CALLBACK WinMain(
- HINSTANCE hInstance,
- HINSTANCE hPrvInstance,
- LPSTR lpCommandLine,
- int cmdShow)
- {
- WCHAR* cln = L"MyApp";
- //设计窗口类
- WNDCLASS wc = {};
- wc.hInstance = hInstance;
- wc.lpszClassName = cln;
- wc.lpfnWndProc = MyWindowProc;
- //注册窗口类
- RegisterClass(&wc);
- // 创建窗口
- HWND hMainwind = CreateWindow(
- cln,
- L"绘制窗口",
- WS_OVERLAPPEDWINDOW,
- 20,
- 12,
- 450,
- 300,
- NULL,
- NULL,
- hInstance,
- NULL);
- // 显示窗口
- if(hMainwind == NULL)
- return 0;
- ShowWindow(hMainwind,SW_NORMAL);
- // 消息循环
- MSG msg;
- while(GetMessage(&msg,NULL,0,0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return 0;
- }
- // 窗口消息处理程序
- LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- switch(msg)
- {
- case WM_PAINT:
- break;
- case WM_DESTROY:
- PostQuitMessage(0);//退出程序
- return 0;
- default:
- return DefWindowProc(hwnd,msg,wParam,lParam);
- }
- }
这个程序是可以正常运行的,我们先来运行一下,看看有什么效果,当然没什么效果,因为只是一个空白窗口。
窗口是正常出现了,但是,现在你试一下改变它的大小时,你人发现有问题了。
这时候我们看到,窗口中有一部分内容变成黑色了,也就是说它没有被重新绘制。当我们的窗口被另一个窗口挡住,然后另一个窗口被移开,我们的程序窗口重新显示时,会发生重绘;但我们改变窗口的大小后,窗口也会发生重绘;当我们把窗口隐藏(如最小化)后再显示,它也会发生重绘。我们的窗口就像一堵墙,在运行期间会不断地被重新粉刷。
要让窗口自动重绘,有一种简单的方法,就是在注册窗口类的时候,设置一个背景色。
- wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
现在你运行的时候,改变窗口的大小,就看不到黑色区域了,因为有了背景色。而上面的代码中,有朋友可能会问,COLOR_WINDOW + 1是什么东西,背景色为什么加1?
我们不妨看看COLOR_WINDOW 的定义。
其实这些都是数值来的,我们看到COLOR_WINDOW是5,那么 5 + 1 就是6吧,你看看6是谁?是不是COLOR_WINDOWFRAME的值?所以,你现在懂了吗,它只是选择COLOR_WINDOW作为参考点,因此,你可以推算到 COLOR_WINDOW - 2是哪个颜色值了。
当窗口需要重新粉刷时,我们的程序都会收到一条WM_PAINT消息,我们可以响应它来完成绘制。
- // 窗口消息处理程序
- LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- switch(msg)
- {
- case WM_PAINT:
- {
- PAINTSTRUCT ps;
- BeginPaint(hwnd, &ps);
- DrawText(ps.hdc, L"朋友,你好。",wcslen(L"朋友,你好。"), &(ps.rcPaint), DT_CENTER);
- EndPaint(hwnd, &ps);
- }
- return 0;
- ...................
我们也许在其他书上看到过,绘制图形要先GetDC来获得一个HDC,然后画图,画完之后再ReleaseDC,为什么我们这里不需要这样做?从代码中我们看到,绘图代码放在BeginPaint和EndPaint之间,这是专门用在处理WM_PAINT消息用的,注意在其他地方不能这样用。
我们用DrawText函数在窗口上绘制了一行文本,但是,在你运行程序后,如果你调整了窗口的大小,你会发现又有新问题出现了。
现在,我们还是来想一想,为啥会出现这种情况呢?
那是因为窗口不是把整个客户区域完全重画,而是判断哪一部分应该重画,就重画,先前因为我们用的都同一种颜色的画刷来填充背景,所以我们看不出问题所在,然现在我们在窗口上绘制了文本,问题就显现出来了。由于每次重画时的矩形范围都是不同的,而且在重画之前没有清除前面的内容,使得新画的东西覆盖在原来的上面,就好像我们拿油漆在墙壁上涂鸦一样。
窗口的客户区域就是你看到的白色的那块矩形,除了标题栏和边框,剩下的那些都可以归为客户区域。
要解决上面问题的最简单方法,就是在设计窗口类的时候,把类样式同时设为水平重画(CS_HREDRAW)和垂直重画(CS_VREDRAW).
- wc.style = CS_HREDRAW | CS_VREDRAW;
现在再运行一下,哈哈,没问题了。
上面的文本是使用默认颜色的绘制的,我想改一下文本的颜色,可以使用SetTextColor函数,第一参数接受一个hdc,第二个参数是COLORREF,通过RGB宏可以创建。如下面的例子:
- case WM_PAINT:
- {
- PAINTSTRUCT ps;
- BeginPaint(hwnd, &ps);
- SetTextColor(ps.hdc, RGB(10, 0, 255));//设置文本颜色
- DrawText(ps.hdc, L"朋友,你好。",-1, &(ps.rcPaint), DT_CENTER);
- EndPaint(hwnd, &ps);
- }
- return 0;
如果想一次性绘制多个字符串,可以调用PolyTextOut函数,但这个函数在绘制出来的字符上好像有点问题。
- case WM_PAINT:
- {
- PAINTSTRUCT ps;
- BeginPaint(hwnd, &ps);
- SetTextColor(ps.hdc, RGB(10, 0, 255));//设置文本颜色
- DrawText(ps.hdc, L"朋友,你好。",-1, &(ps.rcPaint), DT_CENTER);
- // 用于设置每个字符间隔的数组
- int arr1[2]= {45,0};
- int arr2[3] = { 35, 40, 0 };
- int arr3[2] = { 32, 0 };
- POLYTEXT polys[] = { {2,2,3,L"大家",ETO_CLIPPED,ps.rcPaint,&arr1[0]},
- {2,25,3,L"新年好",ETO_CLIPPED,ps.rcPaint,&arr2[0]},
- {30,60,3,L"快乐\0",ETO_CLIPPED,ps.rcPaint,&arr3[0]}
- };
- PolyTextOut(ps.hdc, &polys[0],3);
- EndPaint(hwnd, &ps);
- }
- return 0;
当然也可以填充一些图形区域。
- // 填充图形
- // 创建画刷
- HBRUSH hb = CreateSolidBrush(RGB(0,255,0));
- // 画刷选择到当前DC中
- HBRUSH orgBrs = (HBRUSH)SelectObject(ps.hdc, hb);
- // 填充图形
- Ellipse(ps.hdc,135,35,202,170);
- // 选回原先的画刷
- SelectObject(ps.hdc, orgBrs);
- sp; DeleteObject(hb); //清理对象
这样我们就在窗口上画了一个椭圆了。
响应WM_PAINT消息进行绘图,应按照以下步骤:
1、声明一个PAINTSTRUCT结构体的变量,用于被填充与绘图相关的信息。
2、BeginPaint,函数调用后开始画图。
3、画完之后调用EndPaint函数,HDC会被自动释放。
跟我一起玩Win32开发(3):窗口的重绘的更多相关文章
- 跟我一起玩Win32开发(转自CSDN-东邪独孤)
跟我一起玩Win32开发(1):关于C++的几个要点 跟我一起玩Win32开发(2):完整的开发流程 跟我一起玩Win32开发(3):窗口的重绘 跟我一起玩Win32开发(4):创建菜单 跟我一起玩W ...
- 跟我一起玩Win32开发(17):启动和结束进程
这里我再次说明一下,我不知道为什么,现在的人那么喜欢走极端,估计是价值观都“升级”了的缘故吧. 我撰写这一系列Win32相关的文章,并不是叫大家一定要用Win32去开发项目,仅仅是给大家了解一下,Wi ...
- 跟我一起玩Win32开发(10):绘图(C)
今天我们来欣赏一下用于填充图形的函数,当然我不会逐个去介绍,因为我们参考MSDN直接套参数就可以了. SetDCBrushColor函数有必要扯一下,它的声明如下: COLORREF SetDCBru ...
- 跟我一起玩Win32开发(5):具有单选标记的菜单
帅哥们,美女们,下午好,我又来误人子弟,请做好准备. 今天,我们的目的是,想要实现下图中的这种菜单效果. 就是一种类似单选按钮的菜单,多个菜单项中,同时只有一个会被选中. 首先,我们在资源编辑器中,设 ...
- WM_PAINT消息在窗口重绘的时候产生,那什么时候窗口会重绘(异步工作方式效率高、灵活性强,还有UpdateWindow和RedrawWindow帮忙)
Q:wm_paint消息在窗口重绘的时候产生,那什么时候窗口会重绘?? A: 严格地说,只有当收到WM_PAINT消息后窗口会重绘 但是引起这个消息的事件有很多, 比如:1.首次创建 2.移动 3.改 ...
- 跟我一起玩Win32开发(18):使用对话框的两个技巧
相信大家知道对话框怎么用了,就是先用“资源编辑器”设计一个对话框,然后在代码中加载处理.今天,我向大家分享两个使用对话框的技巧,还是比较实用的.不用担心,先喝杯茶,很简单的,一点也不复杂,总之,看俺写 ...
- 跟我一起玩Win32开发(4):创建菜单
也不知道发生什么事情,CSDN把我的文章弄到首页,结果有不少说我在误人子弟,是啊,我去年就说过了,如果你要成为砖家级人物,请远离我的博客,我这个人没什么特长,唯一厉害的一点就是不相信权威,鄙视砖家,所 ...
- 高性能WEB开发:重排与重绘
DOM编程可能最耗时的地方,重排和重绘. 1.什么是重排和重绘 浏览器下载完页面中的所有组件——HTML标记.JavaScript.CSS.图片之后会解析生成两个内部数据结构——DOM树和渲染树. D ...
- 跟我一起玩Win32开发(14):用对话框作为主窗口
前面我们在编写Win32应用程序的思路都是: 1.设计窗口类.2.注册窗口类.3.创建窗口.…… 然而,当我们接触控件以后, 会发现一个问题,我们在窗口上放置控件实在不好弄,而资源中的对话框具有图形编 ...
随机推荐
- linux下的文件和文件夹的权限问题
1 文件和文件夹的权限 文件和文件夹的权限设置的根本目的是控制人对它们的访问. 2 用户分类 本文件的拥有者.本文件所属的grou.其它用户. 3 也就是说 在读写文件或者文件夹时,要看看自己是属于哪 ...
- app上架的问题
1..p12证书文件(钥匙串导出)开发证书和描述文件的 2.app打包好重Xcode上传到iTunes中的时候最好做校验: 3.程序跑真机出现的问题 解决方法:debug 模式改成release模式 ...
- Studio 3T for MongoDB连接51.212复制集
Studio 3T for MongoDB连接51.212复制集 [ #DirectConection Authentication Mode - Basic(MONGODB-CR or SCEAM- ...
- java里类方法和实例方法
实例方法相对于静态方法(或者叫类方法)而言没有 static 前缀类般方法被对象拥有(也称之实例方法原因)特点定义时候前面没有 static 前缀本类直接调用时候必须也实例方法内否则调用前必须先实例出 ...
- Could not load file or assembly 'System.Web.Http
使用FusLogVw https://stackoverflow.com/questions/4469929/could-not-load-file-or-assembly-or-one-of-its ...
- AndroidStudio——Android SDK
前言 安卓的SDK包,跨过长城下载好的,分享出来一下~ Android Studio版本 | 3.4.1 下载地址 微云下载地址 | 链接:https://share.weiyun.com/5rm6l ...
- Java语言基础二
1.常量的概述和使用 A:什么是常量 B:Java中常量的分类 常量分类为六种:a.”字符串” b.’字符’ c.整数 d.小数 e.boolern(布尔类型) 返回值为 FALSE和TRUE ...
- MYSQL进阶学习笔记四:MySQL存储过程之定义条件,处理过程及存储过程的管理!(视频序号:进阶_11,12)
知识点五:MySQL存储过程之定义条件和处理过程及存储过程的管理(11,12) 定义条件和处理: 条件的定义和处理可以用来定义在处理过程中遇到的问题时相应的处理步骤. DECLARE CONTINUE ...
- Oracle:exp导出exp-00091问题
今天导出一数据库数据,发现EXP-00091问题: 连接到: Oracle Database 10g Enterprise Edition Release - Production With the ...
- [Selenium] 操作 HTML5 中的 Canvas 绘制图形
测试 http://literallycanvas.com/ 以 Chrome Driver 为例阐述,通过 Actions 在 Canvas 上绘制一个封闭图形.对于 Canvas 上的操作,推荐 ...