The program originally wanted to implement a mouse click to change the background color. However, when the program is running, why is no message triggered, the background color has been constantly changed? How the WM_PAINT was triggered.
#include <windows.h>#include<stdlib.h>LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);voidDrawRectangle (HWND);intWINAPI WinMain (hinstance hinstance, hinstance hprevinstance, PSTR szcmdline,inticmdshow) { StaticTCHAR szappname[] = TEXT ("SetBackgroundColor") ; HWND hwnd; MSG msg; Wndclass 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.lpszmenuname=NULL; Wndclass.lpszclassname=Szappname; if(! RegisterClass (&wndclass)) {MessageBox (NULL, TEXT ("Registration failed!"), Szappname, Mb_iconerror); return 0 ; } hwnd= CreateWindow (Szappname, TEXT ("SetBackgroundColor"), Ws_overlappedwindow, Cw_usedefault, Cw_usedefault, Cw_usedefault, cw_usedefault, NULL, NULL, HINSTANCE, NULL); ShowWindow (hwnd, icmdshow); UpdateWindow (HWND); while(GetMessage (&msg,null,0,0) {translatemessage (&msg); DispatchMessage (&msg); } returnMsg.wparam;} LRESULT CALLBACK WndProc (HWND hwnd, UINT imsg, WPARAM WPARAM, LPARAM LPARAM) {StaticRECT R; HDC hdc; Hbrush Hbrush; Switch(imsg) { CaseWm_paint:hbrush= CreateSolidBrush (RGB (rand ()% the, rand ()% the, rand ()% the)); HDC=GetDC (HWND); FillRect (HDC,&R, Hbrush); ReleaseDC (hwnd, HDC); DeleteObject (Hbrush); return 0; CaseWm_size:getclientrect (hwnd,&R); return 0; CaseWm_lbuttondown:invalidaterect (hwnd,&r,true); return 0; CaseWm_destroy:postquitmessage (0) ; return 0 ; } returnDefWindowProc (hwnd, imsg, WParam, LParam);}
Answer: On this basis, take a look at the third chapter of Windows programming.
WM_PAINT is a message generated when there is an invalid zone, so the area should be restored first, so it won't keep looping.
WM_PAINT should use the BeginPaint and EndPaint two APIs, parameters are the paintstruct type, their function is to make the invalid zone recovery
Rather than GetDC and ReleaseDC.
InvalidateRect also has a function that invalidates the zone, which can be manually triggered by the WM_PAINT event redraw
Http://zhidao.baidu.com/question/112410452.html
--------------------------------------------------------------------------------------
Compare Delphi Code:
procedureTwincontrol.wmpaint (varmessage:twmpaint);varDC, MEMDC:HDC; Membitmap, Oldbitmap:hbitmap; ps:tpaintstruct;begin if notFdoublebufferedor(MESSAGE.DC <>0)then//The message has its own DC, which can be drawn with this begin if not(CscustompaintinchControlState) and(Controlcount =0)Then //For Windows self-contained controls, which contain a number of 0 child controls and no self-drawn markup. inherited //to 1, mainly for Windows system native control, Microsoft defined basic control, there is no mistake, should contain beginpaint it? ElsePainthandler (Message); //Trend 2, mainly for the Delphi self-painted control, contains BeginPaint End Else beginDC:= GetDC (0); //Go to 3, the message does not have a DC, then it is now taken, containing BeginPaint Membitmap:=CreateCompatibleBitmap (DC, Clientrect.right, Clientrect.bottom); ReleaseDC (0, DC); MEMDC:= CreateCompatibleDC (0); Oldbitmap:=SelectObject (MEMDC, Membitmap); TryDC:=BeginPaint (Handle, PS); Perform (WM_ERASEBKGND, MEMDC, MEMDC); MESSAGE.DC:=MEMDC; Wmpaint (Message); MESSAGE.DC:=0; BitBlt (DC,0,0, Clientrect.right, Clientrect.bottom, MEMDC,0,0, srccopy); EndPaint (Handle, PS); finallySelectObject (MEMDC, Oldbitmap); DeleteDC (MEMDC); DeleteObject (MEMBITMAP); End; End; end;
procedureTwincontrol.painthandler (varmessage:twmpaint);varI, Clip, Saveindex:integer; DC:HDC; ps:tpaintstruct;beginDC:=MESSAGE.DC; ifDC =0 ThenDC: =BeginPaint (Handle, PS); Try ifFcontrols =Nil ThenPaintwindow (DC)Else beginSaveindex:=SaveDC (DC); Clip:=simpleregion; forI: =0 toFcontrols.count-1 Do withTcontrol (Fcontrols[i]) Do if(Visibleor(csdesigninginchComponentstate) and not(csnodesignvisibleinchControlStyle)) and(CsopaqueinchControlStyle) Then beginClip:= Excludecliprect (DC, left, top, left + Width, top +Height); ifClip = Nullregion ThenBreak ; End; ifClip <> nullregion ThenPaintwindow (DC); RestoreDC (DC, Saveindex); End; Paintcontrols (DC,Nil); finally ifMESSAGE.DC =0 ThenEndPaint (Handle, PS); End;End;
That is, the Twincontrol, whether double buffered or not, invokes the BeginPaint and EndPaint functions to eliminate the self-painting. The entire Controls.pas unit is also called BeginPaint only in these two places.
In addition, I did not find Twincontrol's doublebuffered initialization process, stating that the compiler automatically initialized it to false
WM_PAINT should use the BeginPaint and endpaint these two APIs, their function is to make invalid area recovery (so wm_paint even do nothing, also must write BeginPaint and endpaint)--delphi wm_ Paint message The three trends have done this