- 浏览: 196377 次
- 性别:
- 来自: 长沙
文章分类
最新评论
-
在世界的中心呼喚愛:
思路很好
连连看全局消除算法 -
tianaozhu:
请问,我修改了词库和源文件怎么就不好用了, 我源文件是: My ...
自己动手开发翻译软件(Java版) -
Arlrn:
博主你好,最近在学习排序算法,看了你的博客,你的直接插入排序, ...
各种排序算法的实现及其比较 -
sharong:
有一个明显错误,很显然冒泡排序的时间复杂度是O(n^2)
各种排序算法的实现及其比较 -
julydave:
希尔排序不太对吧。。
各种排序算法的实现及其比较
之前也学了点window编程,但零零碎碎的,知识体系不完整。现在开始,边复习边学新知识。 下面都是在vs2010上写的程序。
#include<windows.h>
#include<stdio.h>
/**
* 本程序中用了Unicode的charset,所以下在用了一些定义的宏。
* 这可以通过:project->……property->configuration properties-> character set来更改。
*/
LRESULT CALLBACK WinLingProc(
HWND hwnd,
UINT uMsg,
WPARAM wPar,
LPARAM lPar
);
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
WNDCLASS wndcls;
wndcls.cbClsExtra = 0;
wndcls.cbWndExtra = 0;
wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndcls.hCursor = LoadCursor(NULL,IDC_HAND);
wndcls.hIcon = LoadIcon(NULL,IDI_HAND);
wndcls.hInstance = hInstance;
wndcls.lpfnWndProc = WinLingProc;
wndcls.lpszClassName = L"ling";
wndcls.lpszMenuName = NULL;
wndcls.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wndcls);
HWND hwnd;
hwnd = CreateWindow(L"ling",L"小凌的窗口",WS_OVERLAPPEDWINDOW,
0,0,600,400,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,1);
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WinLingProc(
HWND hwnd,
UINT uMsg,
WPARAM wPar,
LPARAM lPar
)
{
static int cxChar, cxCaps, cyChar, cyClient, iVscrollPos ;
HDC hdc ;
int i, y ;
PAINTSTRUCT ps ;
TCHAR szBuffer[10] ;
TEXTMETRIC tm ;
const int NUMLINES = 20;
switch(uMsg)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hwnd, hdc) ;
SetScrollRange(hwnd,SB_VERT,0,NUMLINES-1,FALSE);
SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
break;
case WM_CHAR:
TCHAR szChar[20];
wsprintf(szChar ,L"the str is %d",wPar );
MessageBox(hwnd,szChar,L"lingyibin",0);
break;
case WM_LBUTTONDOWN:
MessageBox(hwnd,L"mouse clicked!",L"lingyibin",0);
HDC hdc;
hdc=GetDC(hwnd);
TextOut(hdc,0,50,L"计算机程序设计",wcslen(L"计算机程序设计"));
ReleaseDC(hwnd,hdc);
break;
case WM_PAINT:
HDC hdc2;
PAINTSTRUCT ps;
hdc2 = BeginPaint(hwnd,&ps);
TextOut(hdc2,0,50,L"计算机程序设计",wcslen(L"计算机程序设计"));
EndPaint(hwnd,&ps);
break;
case WM_CLOSE:
if(IDYES == MessageBox(hwnd,L"是否真的关闭窗口?",L"ling",MB_YESNO))
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_SIZE:
cyClient = HIWORD (lPar) ;
return 0 ;
case WM_VSCROLL:
switch (LOWORD (wPar))
{
case SB_LINEUP:
iVscrollPos -= 1 ;
break ;
case SB_LINEDOWN:
iVscrollPos += 1 ;
break ;
case SB_PAGEUP:
iVscrollPos -= cyClient / cyChar ;
break ;
case SB_PAGEDOWN:
iVscrollPos += cyClient / cyChar ;
break ;
case SB_THUMBPOSITION:
iVscrollPos = HIWORD (wPar) ;
break ;
}
default:
return DefWindowProc(hwnd,uMsg,wPar,lPar);
}
}
下面的程序是在窗口中打出字符串,并当鼠标左击时画一个圆。
#include<Windows.h> LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam,LPARAM lParam) { HDC hdc;//设备环境句柄 PAINTSTRUCT ps; RECT rect; POINT point; switch(iMsg) { case WM_PAINT: { hdc = BeginPaint(hwnd,&ps); GetClientRect(hwnd,&rect); DrawText(hdc,"Hello,xiaoling!",-1, //-1 means print all of the characters in "Hello,xiaoling!" &rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER); EndPaint(hwnd,&ps); return 0; } case WM_LBUTTONDOWN: { hdc = GetDC(hwnd); point.x = LOWORD(lParam); point.y = HIWORD(lParam); Ellipse(hdc,point.x-50,point.y-50,point.x+50,point.y+50); ReleaseDC(hwnd,hdc); return 0; } case WM_DESTROY: { PostQuitMessage(0); return 0; } } return DefWindowProc(hwnd,iMsg,wParam,lParam); } int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) { static char szAppName[] = "HelloWin32";//应用程序名 HWND hwnd;//窗口句柄 MSG msg;//消息 WNDCLASSEX wndclass;//窗口类 wndclass.cbSize = sizeof(wndclass);//窗口类结构的大小 wndclass.style = CS_HREDRAW|CS_VREDRAW;//类风格:水平和垂直方向重画 wndclass.lpfnWndProc = WndProc;//窗口过程 wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszClassName = szAppName; wndclass.lpszMenuName = NULL; wndclass.hIconSm = LoadIcon(NULL,IDI_APPLICATION); RegisterClassEx(&wndclass); hwnd=CreateWindow(szAppName, "The Hello App", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd,nShowCmd); UpdateWindow(hwnd); while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }其中有一点要注意的,就是 BeginPaint和GetDC区别
BeginPaint() 和EndPaint() 可以删除消息队列中的WM_PAINT消息,并使无效区域有效。
GetDC()和ReleaseDC()并不删除也不能使无效区域有效,因此当程序跳出 WM_PAINT 时 ,无效区域仍然存在。系统就回不断发送WM_PAINT消息,于是程序不断处理WM_PAINT消息。
相当于BeginPaint、EndPaint会告诉GDI内部,这个窗口需要重画的地方已经重画了,这样WM_PAINT处理完返回给系统后,系统不会再重发WM_PAINT,而GetDC没有告诉系统这个窗口需要重画的地方已经画过,在你把程序返回给系统后,系统一直以为通知你的重画命令你还没有乖乖的执行或者执行出错,所以在消息空闲时,它还会不断地发WM_PAINT催促你画,导致程序卡死。
无效区域 :
无效区域就是指需要重画的区域,无效的意思是:当前内容是旧的,过时的。
假设A是新弹出的一个对话框或被激活的现有对话框,A对话框置于原来的活动对话框B前面,造成对话框B的部分或全部被覆盖,当对话框A移开或关闭后,使对话框B原来被覆盖的地方重新可见。那部分被覆盖的地方就称为无效区域。
只有当一个窗口消息空闲时,系统才会抽空检查一下这个窗口的无效区域是否为非空(WM_PAINT的优先级是最低的。这也就是为什么系统很忙时窗口和桌面往往会出现变白、刷新不了、留拖拽痕迹等现象的原因),如果非空,系统就发送WM_PAINT。所以一定要用BeginPaint、EndPaint把无效区域设为空,否则WM_PAINT将一直被发送。
为什么WINDOWS要提出无效区域的概念?
这是为了加速。
因为BeginPaint和EndPaint用到的设备描述符只会在当前的无效区域内绘画,在有效区域内的绘画会自动被过滤,大家都知道,WIN GDI的绘画速度是比较慢的,所以能节省一个象素就节省一个,不用吝啬,这样可以有效加快绘画速度。
可见BeginPaint、EndPaint是比较“被动”的,只在窗口新建时和被摧残时才重画。
而GetDC用于主动绘制,只要你指到哪,它就打到哪。它不加判断就都画上去,无效区域跟它没关系。对话框没被覆盖没被摧残,它很健康,系统没要求它重画,但开发者有些情况下需要它主动重画:比如一个定时换外观的窗口,这时候就要在WM_TIMER处理代码用GetDC。这时候再用 BeginPaint、EndPaint的话,会因为无效区域为空,所有绘画操作都将被过滤掉。
例子:
PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd,&ps); //Create a DC that matches the device HDC hdcMem = CreateCompatibleDC(hdc); //Load the bitmap HANDLE hBmp= LoadImage(g_hInst_MainWnd,MAKEINTRESOURCE(IDB_MAINWND),IMAGE_BITMAP,0,0,0); //Select the bitmap into to the compatible device context HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp); //Get the bitmap dimensions from the bitmap BITMAP bmp; GetObject(hBmp,sizeof(BITMAP),&bmp); //Get the window area RECT rc; GetClientRect(hWnd,&rc); //Copy the bitmap image from the memory DC to the screen DC BitBlt(hdc,rc.left,rc.top,bmp.bmWidth,bmp.bmHeight,hdcMem,0,0,SRCCOPY); //Restore original bitmap selection and destroy the memory DC SelectObject(hdcMem,hOldSel); DeleteDC(hdcMem); EndPaint(hWnd,&ps); return 0; ///////////////////////// 下面是更加详细的介绍 //======================================================================== //TITLE: // EVC绘制位图--BeginPaint()与GetDC()的区别 //AUTHOR: // norains //DATE: // Tuesday 29-August-2006 //======================================================================== 1.BeginPaint()和GetDC() 在EVC中绘制位图比较方便,有不少现成的函数可供调用,我们所要注意的只是BeginPaint()或GetDC()的使用即可. 因为代码比较简单,所以不做更多解释. 这是消息循环函数: LRESULT CALLBACK MainWndProc(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam) { ...... switch(wMsg) { case WM_PAINT: OnPaintMainWnd(hWnd,wMsg,wParam,lParam); break; ...... } return DefWindowProc(hWnd,wMsg,wParam,lParam); ...... } 响应WM_PAINT消息的函数,在这里进行位图的绘制: LRESULT OnPaintMainWnd(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam) { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd,&ps); //Create a DC that matches the device HDC hdcMem = CreateCompatibleDC(hdc); //Load the bitmap HANDLE hBmp= LoadImage(g_hInst_MainWnd,MAKEINTRESOURCE(IDB_MAINWND),IMAGE_BITMAP,0,0,0); //Select the bitmap into to the compatible device context HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp); //Get the bitmap dimensions from the bitmap BITMAP bmp; GetObject(hBmp,sizeof(BITMAP),&bmp); //Get the window area RECT rc; GetClientRect(hWnd,&rc); //Copy the bitmap image from the memory DC to the screen DC BitBlt(hdc,rc.left,rc.top,bmp.bmWidth,bmp.bmHeight,hdcMem,0,0,SRCCOPY); //Restore original bitmap selection and destroy the memory DC SelectObject(hdcMem,hOldSel); DeleteDC(hdcMem); EndPaint(hWnd,&ps); return 0; }我们都知道BeginPaint()和EndPaint()需要配套使用,并且这两个函数也只能用在WM_PAINT消息的相应函数当中.如果我们在 WM_PAINT的响应函数中将以上两个绘制函数相应替换为GetDC()和ReleaseDC()会有什么结果呢? 即:
HDC hdc = BeginPaint(hWnd,&ps); --> HDC hdc = GetDC(hWnd);
EndPaint(hWnd,&ps); --> ReleaseDC(hWnd,hdc);
编译并运行程序,我们发现窗口一片空白,好像没有绘制位图.但其实不尽然,我们采用单步调试,可以发现其实位图已经绘制出来,只不过又被背景颜色抹掉了. 由此可知,如果需要使用GetDC(),我们对消息循环函数必须要加上对WM_ERASEBKGND的处理:
LRESULT CALLBACK MainWndProc(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam)
{
switch(wMsg)
{
case WM_PAINT:
OnPaintMainWnd(hWnd,wMsg,wParam,lParam);
break;
case WM_ERASEBKGND
return 0;
}
return DefWindowProc(hWnd,wMsg,wParam,lParam);
}
只要系统不对WM_ERASEBKGND进行默认处理,我们用GetDC()替代BeginPaint()就可以正常使用.
至此我们可以看出BeginPaint(),EndPaint()和GetDC(),ReleaseDC()的区别.前一对只能用在WM_PAINT响应函数中,并且绘制背景时不会被抹掉;后一对随处可用,但如果用在WM_PAINT响应函数中,那么接下来将会被WM_ERASEBKGND消息的响应函数的背景绘制给抹掉.
2.绘图闪烁问题
有时候我们大量绘制屏幕时,可能会出现屏幕闪烁问题,这时候可以采用双缓冲的做法.步骤首先是创建一个内存DC,然后往内存DC中绘图,最后把内存DC的内容复制到显示DC中,完成绘制.具体过程并不复杂,结合代码来说明一下.
PS:这段代码也是相应WM_PAINT 消息的.
PAINTSTRUCT ps;
HDC hdc; //获取屏幕显示DC hdc = BeginPaint (hWnd, &ps); //创建内存DC HDC hdcMem = CreateCompatibleDC(hdc); //创建一个bmp内存空间 HBITMAP hBmp = CreateCompatibleBitmap(hdc,SCREEN_WIDTH,SCREEN_HEIGHT); //将bmp内存空间分配给内存DC HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp); //这是使用者需要绘制的画面,全部往内存DC绘制 Rectangle(hdcMem,0,0,SCREEN_WIDTH,SCREEN_HEIGHT); DrawMenuButton(hdcMem); //将内存DC的内容复制到屏幕显示DC中,完成显示 BitBlt(hdc,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,hdcMem,0,0,SRCCOPY); //清除资源 SelectObject(hdcMem,hOldSel); DeleteDC(hdcMem);
发表评论
-
连连看全局消除算法
2012-03-08 01:48 4387好久没写技术博客了。I ... -
object-c笔记一
2011-07-22 11:03 888(本笔记只是简单的记录,只给自己看) 接口的定义: ... -
VC2010中C++的右值引用新特性
2011-05-27 13:37 1509// RightValue.cpp : Defines ... -
linux下用命令编译/调试C++程序
2011-04-01 14:17 3035先安装gcc : sudo apt-get insta ... -
对Windows程序中设备上下文DC(device context)的理解(转)
2010-11-08 00:58 1648对Windows程序中设备上 ... -
MFC学习笔记(九)
2010-10-30 01:47 1382前面已经讲了够多的基础性的东西了,还有一些,但我想还是之后遇到 ... -
MFC学习笔记(八)
2010-10-30 00:55 1045MFC把早期的窗口类的功能分成三个部分:数据存储、管理部分,数 ... -
MFC学习笔记(七)
2010-10-28 01:29 969创建一个普通的Win32 Application,加上一个.c ... -
MFC学习笔记(六)
2010-10-28 01:16 1106先来了解几个类 1、CObject类 有相当一部分类的基 ... -
MFC学习笔记(五)
2010-10-27 01:55 1499早期的MFC应用程序框架结构由两个对象组成:应用程序类CWin ... -
MFC学习笔记(四)
2010-10-27 00:28 1204前面写了那么多代码,但很多东西都是固定的,我们需要写的主要是消 ... -
MFC学习笔记(三)
2010-10-26 14:54 1175这一次修改事件的处理函数,当鼠标左键按下时,可在窗口的用户区显 ... -
MFC学习笔记(二)
2010-10-26 14:31 1011上一篇写的是一个单窗口的程序,这一次写一个多窗口的程序,第一个 ... -
MFC学习笔记(一)
2010-10-26 14:21 1606之前也学过一点MFC的知识,但因很久没去碰就都忘 得差不多了。 ... -
高质量C++/C编程学习笔记(七)----- 其它
2010-10-24 10:29 8011、继承不要随便使用, ... -
高质量C++/C编程学习笔记(六)----- 构造 析构 赋值函数
2010-10-24 10:15 8371、当创建一个类时,C++ ... -
高质量C++/C编程学习笔记(五)----- 基础函数的高级特性
2010-10-24 02:13 11261、重载: 只能靠参数而不能靠返回值类型的不同来区分重载函 ... -
高质量C++/C编程学习笔记(四)----- 内存管理(2)
2010-10-22 00:46 11355、用指针参数传递内存 ... -
高质量C++/C编程学习笔记(三)----- 内存管理(1)
2010-10-22 00:17 11831、 三种内存分配方式 ... -
高质量C++/C编程学习笔记(二)----- 基础
2010-10-21 23:10 9441、在函数体的“入口处” ,用断言对参数的有效性进行检查。断言 ...
相关推荐
这个“win32编程学习笔记”可能包含了关于如何构建、理解和调试Win32应用程序的基础知识和高级概念。 在Win32编程中,开发者需要了解以下关键知识点: 1. **Windows API**:这是Win32编程的核心,提供了大量的函数...
本笔记将深入探讨Win32编程的基本概念、核心原理以及一些实际的例子。 1. **基本概念** - **窗口类(Window Class)**:窗口类定义了一个窗口的属性,如窗口的样式、背景颜色、消息处理函数等。 - **消息队列...
### 达内2013年Win32编程课堂笔记概览 #### 一、编译与连接过程 在Windows编程环境下,特别是针对Win32应用程序开发时,开发者需要了解编译器和连接器的工作原理。编译过程是将源代码(.c或.cpp文件)转换成汇编...
根据提供的文件信息,我们可以归纳出以下关键知识点,主要聚焦于Win32编程的基础概念和技术细节。 ### Win32编程概述 #### 1. Win32编程简介 Win32是微软为Windows操作系统提供的一组应用程序编程接口(API)。Win...
### Win32学习笔记 #### Windows编程基础 在Windows编程中,我们首先需要了解的是基本的概念和编程模型。Windows提供了一套丰富的API(应用程序接口),这些API被封装在不同的动态链接库(DLL)中,例如`kernel32....
### Win32编程知识点概述 #### 一、Win32控件加背景图片 在Win32编程中,为了使用户界面更加美观,通常会给窗口或控件添加背景图片。实现这一功能的方法是通过`WM_PAINT`消息处理来完成。 **示例代码**: ```c++ ...
### Win32程序设计学习笔记知识点概述 #### 1. 背景知识 - **保护模式下的内存管理**:在保护模式下,处理器能够利用32位寄存器访问4GB的内存空间,不再受限于16位寄存器的20位地址空间。为了实现这种内存访问方式...
这个压缩包“win32实例代码和笔记”显然是一个专注于Win32编程的学习资源,包含了代码示例和学习笔记,帮助初学者和有经验的开发者更深入地理解Win32编程。 1. **Win32编程基础** - **窗口程序**:Win32编程的基础...
HINSTANCE hPrevInstance, // 前一个实例句柄,在Win32环境下通常为NULL LPSTR lpCmdLine, // 命令行参数字符串 int nCmdShow // 窗口的显示方式 ) { MessageBox(NULL, "Hello, World!", "Hello", MB_OK); ...
"Win32刘彪笔记"是一份专注于Win32 API编程的学习资料,它包含了作者刘彪在探索这个领域时积累的宝贵经验与知识。Win32 API是Microsoft Windows操作系统的核心接口,开发者可以通过它来实现底层的系统级功能,创建...
ACE编程学习笔记主要涵盖ACE库的安装、配置、编译以及基本的线程管理机制,以下是详细的解释: **1. ACE库的安装** 在Windows XP专业版和Visual Studio 2005环境下安装ACE库涉及以下步骤: 1. 从官方下载站点...
### 串口编程学习笔记,从入门到精通 #### 一、串口定义及基本原理 串口,即串行通信接口,是一种广泛应用于个人电脑(PC)与通信工业中的通信接口。它主要用于低速的数据传输,最常见的标准是RS-232。RS-232接口...
“win32汇编笔记精华”涵盖的内容广泛且深入,不仅包含基础的汇编语言原理,还涉及了Win32平台特有的编程技术和实践应用。对于希望深入理解计算机底层运作、优化程序性能或进行系统级开发的程序员来说,这是一份宝贵...
【Visual Studio 2008 QT编程学习笔记1】这篇笔记主要讲述了如何在Visual Studio 2008中集成和使用QT框架进行GUI开发。以下是关键知识点的详细说明: 1. **QT安装与配置**: - 安装QT:使用的是`qt-win-opensource...
本篇编程笔记涉及了Windows窗体应用程序的初始化、TCP网络编程的基础、线程处理与异步通信以及注册表的操作等几个方面。这些内容对于初学者来说是非常有价值的,可以帮助他们理解如何在C#中实现这些功能。无论是学习...
在实际路径中,还有如`Classes`、`proj.win32`、`Resources`等子目录,它们分别对应类文件、特定平台的项目文件和资源文件。 8. **跨平台开发**:cocos2d-x的一个关键特性是跨平台,使得游戏可以在多个操作系统上...
### S7-200编程软件学习笔记 #### 一、语言设置 在MicroWin V4.0编程软件中,用户可以根据需要选择界面语言。具体操作路径为:**工具** → **选项** → **常规** → **语言**,在此处可以选择“中文”作为软件界面...