??xml version="1.0" encoding="utf-8" standalone="yes"?>
q篇文章帮了我大忙,不过现在q是不知道消除MFC预设的背景色Q前两种Ҏ如何实现Q我对MFC的框架还不是很了?
无闪烁刷屏技术的实现(文章来自:http://www.vchelp.net)
在实现绘囄q程中,昄的图形L会闪烁,W者曾l被q个问题折磨了好久,通过向高手请教,搜烦资料Q问题一基本解决Q现文档整理出来以供大家参?
1. 昄的图形ؓ什么会闪烁Q?br>我们的绘图过E大多放在OnDraw或者OnPaint函数中,OnDraw在进行屏q显C时是由OnPaintq行调用的。当H口׃M原因需要重l时QL先用背景色将昄区清除,然后才调用OnPaintQ而背景色往往与绘囑ֆ容反差很大,q样在短旉内背景色与显C图形的交替出现Q得显C窗口看h在闪。如果将背景刯|成NULLQ这h论怎样重绘囑Ş都不会闪了。当Ӟq样做会使得H口的显CZؕ成一团,因ؓ重绘时没有背景色对原来绘制的囑Şq行清除Q而又叠加上了新的囑Ş。有的h会说Q闪烁是因ؓl图的速度太慢或者显C的囑Ş太复杂造成的,其实q样说ƈ不对Q绘囄昄速度寚w烁的影响不是Ҏ性的。例如在OnDraw(CDC *pDC)中这样写Q?br>pDC->MoveTo(0,0);
pDC->LineTo(100,100);
q个l图q程应该是非常简单、非常快了吧Q但是拉动窗口变化时q是会看见闪烁。其实从道理上讲Q画囄q程复杂越慢闪烁应该越,因ؓl图用的旉与用背景清除屏幕所q旉的比例越大h寚w烁的感觉会越不明显。比如:清楚屏幕旉?sl图旉也是?sQ这样在10s内的q箋重画中就要闪?ơ;如果清楚屏幕旉?s不变Q而绘图时间ؓ9sQ这?0s内的q箋重画只会闪烁一ơ。这个也可以试验Q在OnDraw(CDC *pDC)中这样写Q?br>for(int i=0;i<100000;i++)
{
pDC->MoveTo(0,i);
pDC->LineTo(1000,i);
}
呵呵Q程序有点变态,但是能说明问题?br> 说到q里可能又有说了Qؓ什么一个简单图形看h没有复杂囑Ş那么闪呢Q这是因为复杂图形占的面U大Q重L造成的反差比较大Q所以感觉上要闪得厉害一些,但是闪烁频率要低。那Z么动ȝ重画频率高,而看h却不闪?q里Q我p再次了,闪烁是什么?闪烁是反差Q反差越大,闪烁厉実뀂因为动ȝq箋两个帧之间的差异很小所以看h不闪。如果不信,可以在动ȝ每一帧中间加一张纯白的帧,不闪才怪呢?br>2、如何避免闪?br> 在知道图形显C闪烁的原因之后Q对症下药就好办了。首先当然是LMFC提供的背景绘制过E了。实现的Ҏ很多Q?br>* 可以在窗口Ş成时l窗口的注册cȝ背景刷付NULL
* 也可以在形成以后修改背景
static CBrush brush(RGB(255,0,0));
SetClassLong(this->m_hWnd,GCL_HBRBACKGROUND,(LONG)(HBRUSH)brush);
* 要简单也可以重蝲OnEraseBkgnd(CDC* pDC)直接q回TRUE
q样背景没有了,l果囑Ş昄的确不闪了,但是昄也象前面所说的一P变得一团ؕ。怎么办?q就要用到双~存的方法了。双~冲是除了在屏q上有图形进行显CZ外,在内存中也有囑Ş在绘制。我们可以把要显C的囑Ş先在内存中绘制好Q然后再一ơ性的内存中的图形按照一个点一个点地覆盖到屏幕上去Q这个过E非常快Q因为是非常规整的内存拷贝)。这样在内存中绘图时Q随便用什么反差大的背景色q行清除都不会闪Q因为看不见。当贴到屏幕上时Q因为内存中最l的囑Ş与屏q显C图形差别很(如果没有q动Q当然就没有差别Q,q样看v来就不会闪?br>3、如何实现双~冲
首先l出实现的程序,然后再解释,同样是在OnDraw(CDC *pDC)中:
CDC MemDC; //首先定义一个显C备对?br>CBitmap MemBitmap;//定义一个位囑֯?br>//随后建立与屏q显C兼容的内存昄讑֤
MemDC.CreateCompatibleDC(NULL);
//q时q不能绘图,因ؓ没有地方?^_^
//下面建立一个与屏幕昄兼容的位图,至于位图的大嘛Q可以用H口的大?br>MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);
//位N入到内存显C备中
//只有选入了位囄内存昄讑֤才有地方l图Q画到指定的位图?br>CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);
//先用背景色将位图清除q净Q这里我用的是白色作?br>//你也可以用自己应该用的颜?br>MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));
//l图
MemDC.MoveTo(…?;
MemDC.LineTo(…?;
//内存中的图拯到屏q上q行昄
pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);
//l图完成后的清理
MemBitmap.DeleteObject();
MemDC.DeleteDC();
上面的注释应该很详尽了,废话׃多说了?br>4、如何提高绘囄效率
实际上,在OnDraw(CDC *pDC)中绘制的囑ƈ不是所有都昄了的Q例如:你在OnDraw中画了两个矩形,在一ơ重l中虽然两个矩Ş的绘制函数都有执行,但是很有可能只有一个显CZQ这是因为MFC本nZ提高重绘的效率设|了裁剪区。裁剪区的作用就是:只有在这个区内的l图q程才会真正有效Q在区外的是无效的,即在区外执行了l图函数也是不会昄的。因为多数情况下H口重绘的生大多是因ؓH口部分被遮挡或者窗口有滚动发生Q改变的区域q不是整个图形而只有一部分,q一部分需要改变的是pDC中的裁剪Z。因为显C(往内存或者显存都叫显C)比绘图过E的计算要费时得多,有了裁剪区后昄的就只是应该昄的部分,大大提高了显C效率。但是这个裁剪区是MFC讄的,它已lؓ我们提高了显C效率,在进行复杂图形的l制时如何进一步提高效率呢Q那只有去掉在裁剪区外的绘图过E了。可以先用pDC->GetClipBox()得到裁剪区,然后在绘图时判断你的囑Ş是否在这个区内,如果在就画,不在׃甅R?br>如果你的l图q程不复杂,q样做可能对你的l图效率不会有提高?/p>
我的临时文Q看h好ؕQ程序里的标识符也没完全按文里的来Q真是ؕ套了Q明天好好修改修攏V?/p>
攑օMyDefine.h,MyDefine.cpp文g
1Q?河的边线
Doc里放入:
//num of ctrl pnt,nodal pnt,display style,
//wave speed wave distance and wave num
int ctrlNum,ndlNum,style,wSpeed,wDistance,wNum;
//the pnt array represent ctrl pnts and nodal pnts.
CArray <CPoint,CPoint&> c_PntsL,c_PntR,n_PntsL,n_PntsR;
视图cd文档c都要引?/b>MyDefine.hQ用Q?/b>ifndef?/b>
以下内容攑֜视图c里的OnCreate函数中,先ؓCView的派生类声明一个图元文件的数据成员HMETAFILE m_hMetaFile;
CArray <CPoint,CPoint&> initL,initR;
//预先输入的控制点Q自定义
Int const Max=60;
//CArray <CPointPartner,CPointPartner&> init_CPntPtr,final_CPntPtr;
//CPointPartner作ؓTYPE有问题,q是用数l?
//改ؓ:
CPointPartner init_CPntPtr[Max],final_CPntPtr[Max];
//最后的点对数组final_CPntPtrlCCurvecȝ
While(i<Num)
{
CPointPartner temp_CPntPtr (initL[i],initR[i]);
init_CPntPtr.Add(temp_CPntPtr);
i++;
}
//鼠标点击或预先指定控制点Q即一些点?
//以及处理后得到的点对
CSpline spL (initL);
CSpline spR (initR);
//两边的样条曲U?
CArray<CPoint,CPoint&> finalL,finalR;
//处理后得到的h曲线上的?
spL.GetPoints(finalL);
spR.GetPoints(finalR);
Count=finalL.GetSize();
For(int i=0;i<count;i++)
{
CPointPartner Temp_finalP (finalL[i],finalR[i])
Final_CPntPtr[i]=temp_finalP;//重蝲Q运符
}
//样条对象spLQspR里的Ҏ入finalL和finalR,之后又放入点Ҏlfinal_CPntPtr;
//共count个点?
CMetaFileDC metaFileDC;
metaFileDC.Create();
q里d边线Q通过finalL和finalRQ?/b>
m_hMetaFile=metaFileDC.Close();
5Q?3?9Q?0以上E序的调试已完成Q未加鼠标控Ӟ
2Q?一道道波纹Q?/b>CCurvec)
在视囄中声明数据:CArray<Points,Points&> mPntsCurve;
在OnDraw?
先确定水波位|:
WavePL[i]和WavePR[i]
ForQint i=0,i<WaveN;i++Q?
{
CCurve tempCurve (final_CPntPtr[i]);
tempCurve.ComputePnts(mPntsCurve);
q这些点成线
}
详细设计Q?
Doc里定义两个点Q?
View里定义一个函数BOOL ComputePnts(CArray<CPoint,CPoint&>& m_Pnts,CPoint m_LPnt,CPoint m_RPnt)
OnDraw里给两个点赋|调用ComputePntsQ再l图
?/b>MFC的联p?/b>
//用图元文件保存边U,中间的curvexd?/b>
//要描l的点,每两点画条线q接LineTO
或者将炚w的计都攑֜文cMQ给文cLZ个函?/b>
数据的放|位|还得琢琢?/b>
5Q?1 ?2Q?0此文档完?/b>
Spline的计在CDoc里,Curve的计在CView?/b>
5. 29 ?Q?7 dQ明天再修改Q?/b>
5.30
Q: Spline里的tempg得数l越界问?/b>
A: _ֺ造成的,两个float型变量t和T1[j1+1]都ؓ0.90000,但t>T1[j1+1]为true,
TipsQ?/b>
1Q?查找cd强制转换以及_ֺ丢失的知?/b>
2Q?看林锐的《高质量C++~程》,注意q些l节?/b>
5.31
已完成:位图作ؓ背景?/b>
Q:鼠标控制的问?/b>
2、API,全称application program interface,意思是应用E序~程接口(说vAPIq不仅仅指windows而言Q?windows支持的API叫winapi)。winapi是应用E序和windows之间通讯的一个编E界面。windows提供了上千个API函数Q以方便E序员来~写应用E序?/p>
3、WinSDKE序设计是API方式的windowsE序设计。SDK,全称Software Developers Kit,意思是软g开发工L?/p>
4、MFC,全称Microsoft Foundation Classes,伪Y把WinAPIq行装的类库。它是一个类的集合,通过覆盖WinAPIQؓ~程提供了一个面向对象的界面。它使windowsE序员能够利用C++面象对象的特性进行编E,cMBCB的OWLQDelphi的VCLlg。它把那些进行SDK~程时最J琐的部分提供给E序员,使之专注于功能的实现。你不妨把它惌成类似TC提供的函数库吧?/p>
5、dos下的C~程的main()一Pwindows下的入口是WinMain()函数?/p>
6、WinMain()所L作用Q初始化Q展C,销毁应用程序等?br>W一个参敎ͼ应用E序的当前实例句柄?br>W二个参敎ͼ应用E序的前一个实例句柄,别管它,对于Win32位而言Q它一般是NULL.
W三个参敎ͼ指向M传给E序的命令行参数。PSTR代表"指向字符串的指针"?br>W四个参敎ͼ它告诉应用程序如何初始化H口Q如最大化Q最化{状态?/p>
7、句?handle)Q?br>在标准C库中句柄用来Ҏ件输入输出?br>在Windows环境中,句柄是用来标识项目的Q这些项目包括:
*.模块(module)
*.d(task)
*.实例(instance)
*.文g(file)
*.内存?block of memory)
*.菜单(menu)
*.控制(control)
*.字体(font)
*.资源(resource),包括图标(icon)Q光?cursor)Q字W串(string){?br>*.GDI对象(GDI object),包括位图(bitmap),d(brush),元文?metafile),调色?palette),?W?pen),区域(region),以及讑֤描述?device context)?br>WINDOWSE序中ƈ不是用物理地址来标识一个内存块Q文Ӟd或动态装入模块的Q相反的QWINDOWS APIl这些项目分配确定的句柄Qƈ句柄返回给应用E序Q然后通过句柄来进行操作?/p>
H口句柄Q?br>pȝ通过H口句柄来在整个pȝ中唯一标识一个窗口,发送一个消息时必须指定一个窗口句柄表明该消息由那个窗口接收。而每个窗口都会有自己的窗口过E,所以用L输入׃被正的处理?/p>
8、所有的命名采用了匈牙利表示法。如消息的前~使用msg.句柄使用h.函数使用fn{?/p>
9、MainFrm.cpp、MainFrm.hQ?br>q两个文件将从CFrameWnd(SDI应用E序)或CMDIFrameWnd(MDI应用E序)zCMainFramecR如果在AppWizard的Application Options(6步中的第4步)中选择了对应的可选项的话QCMainFramecd处理工具条按钮和状态条的创建。MAINFRM.CPP文gq含有MFC应用E序提供的默认工h按钮的对象ID——叫做buttons数组?/p>
10、DOSE序主要使用序的,q程驱动的程序设计方法。顺序的Q过E驱动的E序有一个明昄开始,明显的过E及一个明昄l束Q因此程序能直接控制E序事g或过E的序。虽然在序的过E驱动的E序中也有很多处理异常的ҎQ但q样的异常处理也仍然是顺序的Q过E驱动的l构?/p>
11、Windows的驱动方式是事g驱动Q就是不׃件的序来控Ӟ而是׃件的发生来控Ӟ所有的事g是无序的。做Z个程序员Q在你编写程序时Q你q不知道用户先按哪个按纽Q也不知道程序先触发哪个消息。你的Q务就是对正在开发的应用E序要发出或要接收的消息q行排序和管理。事仉动程序设计是密切围绕消息的生与处理而展开的,一条消息是关于发生的事件的消息?/p>
12、WindowsE序则至两个主E序Q?br>一个是WinMain(),
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
);
另一个是H口q程函数WndProc,它的函数原型?
long FAR PASCAL WndProc(HWND hWnd,WORD message,WORD wParam,LONG lParam);
13、窗口函C回调函数:
在Windows中,应用E序通过要求Windows完成指定操作Q而承担这w信d的API函数是Windows的相应窗口函数WndProc。应用程序不直接调用MH口函数Q而是{待Windows调用H口函数Q请求完成Q务或q回信息。ؓ保证Windows调用q个H口函数Q这个函数必d向Windows登记Q然后在Windows实施相应操作时回调,所以窗口函数又UCؓ回调函数。WndProc是一个主回调函数QWindows臛_有一个回调函数。典型的回调函数有窗口过E、对话框q程和钩子函数。实际上Q也许有不止一个的H口q程。例如,每一个不同的H口c都有一个与之相对应的窗口过E?/p>
15、实?在Windows中,能多ơ同时运行同一个应用程序,卌行多个副本,每个副本叫做一?#8220;实例”?/p>
16、C runtime函数库:
p它的名字一?q行cd信息
主要有COjectcdCRuntimeClasscL实现,用来存贮COjectcdzcȝq行cd信息,
1.cȝ基本情况:如类的名?存贮I间大小,用于q行cȝcd定.
2.ms在C++的标准上,d动态创建的cd象功?也就是时时提到的动态创?br>3.串行化处?
The OS does not know main(), so C-runtime is first called and transfer control to main
it also provide library for common usage, such as math functions
17、WinMain()函数的调用约定是PASCAL?/p>
在这里PASCAL是一个调用约定,׃q种方式最早由PASCAL采用Q所以这么叫?br>在MSDN中的C++ Language Reference中,Calling Conventionsq一章都是讲调用U定的?/p>
U定Q微软重定义了许多约定类型,为的是可以让代码更容易跨q_或者跨~译器?br>其实Q调用约定要解决两个问题Q都是针对堆栈操作:
1。参C递的序Q本质是压栈的顺序)
2。谁负责qxQ调用者还是调用对象)
一个函数的声明、定义和实现中的调用方式一般都一致?/p>
WINAPI标识W的定义是:#define WINAPI __stdcall, __stdcall指Window调用函数的一U方式,也就是如何在堆中存取函数参数的方式。许多Windows Api函数调用声明为__stdcall方式?/p>
18、用位的“?#8221;操作Q操作符“|”Q把若干个常数组合v来控制消息窗口显C的按钮和图标等?/p>
19、在Windows应用E序中,每一个窗口都必须从属于一个窗口类Q窗口类定义了窗口所h的属性,如它的样式、图标、鼠标指针、菜单名U及H口q程名等?br>H口U类是定义窗口属性的模板,q些属性包括窗口式?鼠标形状,菜单{等,H口U类也指定处理该cM所有窗口消息的H口函数.只有先徏立窗口种c?才能ҎHU类来创建Windows应用E序的一个或多个H口.创徏H口?q可以指定窗口独有的附加Ҏ?HU类U窗口类,H口cM能重?在徏立窗口类?必须向Windows登记.建立H口cd是用WNDCLASSl构定义一个结构变?
20、Visual C++提供Alt+F8功能键,q行文g规格化,Ҏ周围的代码行Q正羃q选定的代码行。常使用该按键可使得文g保持规格?注,Alt+F8功能键对q箋两个CASE语句则会发生处理错误Q不能规格化)?
21、消息:
一个消息由一个消息名U?UINT)Q和两个参数(WPARAMQLPARAM)。当用户q行了输入或是窗口的状态发生改变时pȝ都会发送消息到某一个窗口?/p>
22、一个典型的应用E序应该zd在称?#8220;框架H口”中。一个框架窗口是一个全功能的主H口Q用户可以改变尺寸、最化、最大化{?/p>
23、消息机Ӟ
pȝ会l护一个或多个消息队列Q所有生的消息都回被放入或是插入队列中。系l会在队列中取出每一条消息,Ҏ消息的接收句柄而将该消息发送给拥有该窗口的E序的消息@环。每一个运行的E序都有自己的消息@环,在@环中得到属于自己的消息ƈҎ接收H口的句柄调用相应的H口q程。而在没有消息时消息@环就控制权交给pȝ所以Windows可以同时q行多个d?/p>
24、预~译头文?
VC++E序一般包含的头文仉比较复杂Q如果每ơ都逐行分析可能会花很多旉Q所以VC++默认讄是第一ơ编译时分析所有头文gQ生?pch文gQ这个文件很大,但以后每ơ编译时可以节省很多时间。如果删除了q个文gQ下ơ编译时VC++会自动生成它?
StdAfx.h是每个MFCE序的类中必d括的文gQ它一般由AppWizard自动生成Q包括编译MFCcL必须的定义?/p>
25、Windows支持两种cd的对话框Q模式和无模式对话框?br>模式对话框一旦出现在屏幕上,只有当它退出时Q屏q上该应用程序的其余部分才能响应?br>无模式对话框出现在屏q上ӞE序的其余部分也可以作出响应Q它p动在上面一栗?/p>
26、单文界面(SDI)Q只有一个框架窗口?br>MDI pȝ允许用户在同一应用E序中同时可以查看多个文?/p>
/*Win32应用E序框架主要?初始化窗口类"Q?H口注册c?Q?H口的创??H口消息函数"{组?/
#include "stdafx.h"
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); //H口函数说明
/*
WinMain函数是所有windows应用E序的入口,cM于C语言中的Main函数Q其功能是完成一pd的定义和初始化工作,q生消息@环。消息@环是整个E序q行的核心。WinMain函数实现以下功能?br> 1. 注册H口c,建立H口及执行其它必要的初始化工作;
2. q入消息循环Q根据从应用E序消息队列接受的消息,调用相应的处理过E?br> 3. 当消息@环检索到WM_QUIT消息时终止程序运行?/p>
WinMain函数有三个基本的l成部䆾Q函数说明、初始化和消息@环?/p>
WinMain函数的说明如下:
int WINAPI WinMain( //WinMain函数说明
HINSTANCE hInstance, //E序当前实例句柄
HINSTANCE hPrevInstance, //应用E序其它实例句柄
LPSTR lpCmdLine, //指向E序命o行参数的指针
int nCmdShow //应用E序开始执行时H口昄方式的整数值标?br>)
׃Window操作pȝ是多d的操作系l,能进行多d的管理,因此Qwindows应用E序可能被ƈ行的多次执行Q因而可能出现同一个程序的多个H口同时存在的情况,Windowspȝ应用程序每一ơ执行称应用E序的一个实例(InstanceQ,q用一个实例句柄唯一的标识它?/p>
*/
int APIENTRY WinMain(HINSTANCE hInstance, //WinMain函数说明
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
/*
采用Pascal的变量定义风|卛_E序Q函敎ͼ开始处定义所有变?br> 虽然CQ+的变量定义比较灵z,本程序ؓ了ɽE序易于理解,未采用这U方?br> */
char lpszClassName[]="H口"; //H口cd
char lpszTitle[]="Windows SDK~程之一 H口CZE序"; //H口标题?/p>
//---------------H口cd?------------------------------------
/*
H口cȝ定义
在Windows应用E序中,H口宛_义了H口的Ş式与功能。窗口类定义通过l窗口类数据l构WNDCLASS赋值完成,该数据结构中包括H口cȝ各种属性,在窗口类定义q程中常用到以下函数Q?br> */
WNDCLASS wndclass;
wndclass.style=0; //H口cd为缺省类?br> wndclass.lpfnWndProc=WndProc; //H口处理函数为WndProc
wndclass.cbClsExtra=0; //H口cL扩展
wndclass.cbWndExtra=0; //H口实例无扩?br> wndclass.hInstance=hInstance; //当前实例句柄
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); //使用~省图标
/*
LoadIconQ)Q在应用E序中加载一个窗口图?br> LoadIconQ)函数原型为:
HICON LoadIconQ?br> HINSTANCE hInstance,//图标资源所在的模块句柄QؓNULL则用系l预定义图标
LPCTSTR lpIconName //图标资源名或pȝ预定义图标标识名
)
*/
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); //H口采用头光标
/*
LoadCursor():在应用程序中加蝲一个窗口光?br> LoadCursor()函数原型为:
HCURSOR LoadCursorQ?br> HINSTANCE hInstance,//光标资源所在的模块句柄QؓNULL则用系l预定义光标
LPCTSTR lpCursorName //光标资源名或pȝ预定义光标标识名
)
*/
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); //H口背景为白?br> /*
GetStockObjectQ)Q获取已l定义的ȝ、画列字体等对象的句?br> GetStockObjectQ)函数原型为:
HGDIOBJ GetStockObjectQint fnObjectQ? //fnObject为对象的标识?/p>
*/
wndclass.lpszMenuName=NULL; //H口中无菜单
wndclass.lpszClassName=lpszClassName; //H口cd?H口实例'
//------------------以下是进行窗口类的注?--------------------------
/*
注册H口c?br> Windowspȝ本n提供部䆾预定义的H口c,E序员也可以自定义窗口类Q窗口类必须先注册后使用。窗口类的注册由注册函数RegisterClassQ)实现。其形式?
RegisterClass(&wndclass)
&wndclass为窗口类l构
RegisterClass函数的返回gؓ布尔?注册成功则返回真
*/
if (! RegisterClass(&wndclass)) //注册H口Q若p|Q则发出声音
{ MessageBeep(0);
return FALSE;
}
/*
创徏H口实例
创徏一个窗口类的实例由函数CreateWindow()实现,该函数的原型?
HWND CreateWindow(LPCTSTR lpszClassName, //创徏H口Q窗口类?br> LPCTSTR lpszTitle, //H口实例的标题名
DWORD dwStyle, //H口的风?br> int x, //H口左上角坐?br> int y, //H口左上角坐?br> int nWidth, //H口的宽?br> int nHeight, //H口的高?br> HWND hwndParent, //此窗口父H口
HWENU hMenu, //此窗口主菜单
HINSTANCE hInstance, //应用E序当前句柄
LPVOID lpParam); //指向一个传递给H口的参数值的指针
*/
//创徏H口操作
HWND hwnd; //H口l构
hwnd=CreateWindow(lpszClassName, //创徏H口Q窗口类?br> lpszTitle, //H口实例的标题名
WS_OVERLAPPEDWINDOW, //H口的风?br> CW_USEDEFAULT,CW_USEDEFAULT, //H口左上角坐标ؓ~省?br> CW_USEDEFAULT,CW_USEDEFAULT, //H口的高度和宽度为缺省?br> NULL, //此窗口无父窗?br> NULL, //此窗口无主菜?br> hInstance, //应用E序当前句柄
NULL); //不用该?/p>
ShowWindow(hwnd,nCmdShow); //昄H口
UpdateWindow(hwnd); //l制用户?br>
/*
消息循环
windows应用E序的运行以消息为核心。windows生的消息攑օ应用E序的消息队列中而应用程序WinMain函数的消息@环提取消息队列中的消息,q将其传递给H口函数为相应处理过E处理?br> MSG msg; //消息l构
while( GetMessage(&msg,NULL,0,0)) //消息循环
{ TranslateMessage(&msg);
DispatchMessage(&msg);
}
*/
MSG msg; //消息l构
/*GetMessage()作用Q从消息队列中读取一条消息,q将消息攑֜一个MSGl构中:
BOOL GetMessage(
LPMSG lpMsg, //指向MSGl构的指?br> HWND hWnd,
UINT wMsgFilterMin, //用于消息qo的最信息号?br> UINT wMsgFilterMax //用于消息qo的最大信息号?如最值和最大值均?Q?则不qo消息
);
当GetMessageq回0Ӟx索到WM_QUIT消息Q程序将l束循环q?/p>
BOOL TranslateMessage( const MSG *lpMsg ); 负责把消息的虚拟键D{换ؓ字符信息
LRESULT DispatchMessage( const MSG *lpmsg ); 参数lpmsg指向的消息传递给指定的窗?/p>
*/
while( GetMessage(&msg,NULL,0,0)) //消息循环
{ TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam; //E序l止Ӟ信息返回操作系l?br>}
//-----------------------------H口函数---------------------------------------
/*
H口消息处理函数定义了应用程序对接收到的不同消息的响应,它包含了应用E序对各U可用接收到的消息的处理q程Q通常 Q窗口函数由一个或多个switch...case语句l成Q每一条case语句
对应一U消息,当应用程序接收到一个消息时Q相应的case语句被 Ȁzdƈ执行相应的响应程序模块?br>H口函数的一般Ş式如下:
LRESULT CALLBACK WindowProc( HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
Parameters
hwnd Q[in] Handle to the window.
uMsg Q[in] Specifies the message.
wParamQ[in] Specifies additional message information. The contents of this parameter depend on the value of the uMsg parameter.
lParamQ[in] Specifies additional message information. The contents of this parameter depend on the value of the uMsg parameter.
Return Value
The return value is the result of the message processing and depends on the message sent.
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case ...
....
break;
.........
case WM_DESTROY:
//void PostQuitMessage(int nExitCode)函数的作用是向程序发送WMQQUIT消息QnExitCode应用E序退Z?br> PostQuitMessage(0); //调用该函数发出WM_QUIT消息
default: //~省消息处理函数,以保证所的发往H口的消息都能被处理
return DefWindowProc(hwnd,message,wParam,lParam);
}
return (0);
}
*/
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0); //调用该函数发出WM_QUIT消息
default: //~省消息处理函数
return DefWindowProc(hwnd,message,wParam,lParam);
}
return (0);
}
/*
注:
事g驱动的特点:
WindowsE序设计围绕着事g或消息的产生驱动产生q行消息处理函数。WindowsE序的执行顺序取决于事g发生的顺序,E序的执行是由顺序生的消息驱动的,E序员可以针Ҏ息类型编写消息处理程序以处理接收的消息,或者发出其他消息以驱动其他处理E序Q但是不必预先确定消息的产生序。这是面向对象编E中事g驱动的显著特炏V?br> 事g驱动~程Ҏ对于~写交互E序很有用处Q用q一Ҏ~写的程序ɽE序避免了死板的操作模式Q从而用户能够按照自己的意愉K用灵zd变的操作模式?br> Windows应用E序中的消息传递机Ӟ
VC中存在几U系l定义的消息分类Q常用的消息q口消息、初始化消息、输入消息、系l消息、剪切板消息、文当界面消息、DDEQ动态数据交换)消息、应用程序自定义消息{。应用程序发送的消息发送至消息队列Q系l根据消息到辄序Ҏ息进行处理,q调用响应的消息处理模块代码?br>*/