user-0 提问: 为什么WM_PAINT外的BeginPaint无法绘画

回复:
user: user-1
content: 在WM_PAINT意外的其它的地方，你可以使用GetDC()/ReleaseDC()绘图

user: user-1
content: 你调用BeginPaint应该在WM_PAINT消息响应函数中，而不应该在其它的消息响应中~

user: user-2
content: MSDN98_1.ISO http://pan.baidu.com/s/1dDF41ix,  MSDN98_2.ISO http://pan.baidu.com/s/1bnGo0Vl

user: user-2
content: BeginPaint The BeginPaint function prepares the specified window for painting and fills a PAINTSTRUCT structure with information about the painting.   HDC BeginPaint(   HWND hwnd,  // handle to window   LPPAINTSTRUCT lpPaint               // pointer to structure for paint information );   Parameters hwnd  Handle to the window to be repainted.  lpPaint  Pointer to the PAINTSTRUCT structure that will receive painting information.  Return Values If the function succeeds, the return value is the handle to a display device context for the specified window.   If the function fails, the return value is NULL, indicating that no display device context is available.   Windows NT: To get extended error information, callGetLastError.  Remarks The BeginPaint function automatically sets the clipping region of the device context to exclude any area outside the update region. The update region is set by the InvalidateRect or InvalidateRgn function and by the system after sizing, moving, creating, scrolling, or any other operation that affects the client area. If the update region is marked for erasing, BeginPaint sends a WM_ERASEBKGND message to the window.   An application should not call BeginPaint except in response to a WM_PAINT message. Each call to BeginPaint must have a corresponding call to the EndPaint function.   If the caret is in the area to be painted, BeginPaint automatically hides the caret to prevent it from being erased.   If the window's class has a background brush, BeginPaint uses that brush to erase the background of the update region before returning.   QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Requires version 1.0 or later.   Header: Declared in winuser.h.   Import Library: Use user32.lib.  See Also Painting and Drawing Overview, Painting and Drawing Functions, EndPaint, InvalidateRect, InvalidateRgn, PAINTSTRUCT, ValidateRect, ValidateRgn

user: user-3
content: The function returns the previous DC_PEN color, even if the stock pen DC_PEN is not selected in the DC; however, this will not be used in drawing operations until the stock DC_PEN is selected in the DC.

user: user-3
content: 引用 11 楼 六道佩恩 的回复:话说你知道SetDCPenColor无效是怎么一回事吗？设置颜色后，画笔颜色没改变，但GetDCPenColor获取颜色的结果却是已改变 case WM_PAINT:       {          // Initializing original object          HGDIOBJ original = NULL;                   hdc = BeginPaint(h, &ps);          Arc(hdc, 100, 100, 300, 200, 0, 0, 0, 0);          // Saving the original object          // and Select DC_PEN so you can change the color of the pen with          // COLORREF SetDCPenColor(HDC hdc, COLORREF color)          original = SelectObject(hdc, GetStockObject(DC_PEN));          // Set the Pen to Blue          SetDCPenColor(hdc, RGB(0, 0, 255));          Arc(hdc, 200, 100, 300, 200, 0, 0, 0, 0);          // Restoring the original object          SelectObject(hdc, original);          EndPaint(h, &ps);       }       return 0;

user: user-2
content: 为什么不行，闲来无事可以参考一下Win2000源代码相关片段。 我说这句话的意思并不是意味着我看过哈。我只是扶上马，送一程。 https://bbs.csdn.net/topics/390374955

user: user-0
content: 引用 8 楼 user-3 的回复:问题在于hdc不能跨消息使用  话说你知道SetDCPenColor无效是怎么一回事吗？设置颜色后，画笔颜色没改变，但GetDCPenColor获取颜色的结果却是已改变

user: user-0
content: 引用 8 楼 user-3 的回复:问题在于hdc不能跨消息使用  #include "windows.h" LRESULT MyProc( HWND h , UINT msg , WPARAM wParam , LPARAM lParam ) { 	static PAINTSTRUCT ps; 	static HDC hdc; 	switch( msg ) 	{ 		case WM_SIZE: 			hdc = BeginPaint( h , &ps ); 			InvalidateRect( h , NULL, 0 ); 			return 0; 			  		case WM_PAINT: 		{	 			SendMessage( h , WM_ERASEBKGND , hdc , 0 ); 			Arc( hdc , 100,100,300,200,0,0,0,0 ); 			ValidateRect( h , NULL );  			return 0; 		} 	 		case WM_LBUTTONDOWN: 			InvalidateRect( h , NULL , 0 ); 			return 0; 	 		case WM_DESTROY: 			PostQuitMessage(0); 			EndPaint( h , &ps ); 			return 0; 	} 	return DefWindowProc( h , msg , wParam , lParam ); } void SetWNDCLASS( WNDCLASS* a, WNDPROC proc, LPCTSTR ClassName ) { 	a->style 			=CS_HREDRAW | CS_VREDRAW; 	a->lpfnWndProc		=proc;							 	a->cbClsExtra		=0;		 	a->cbWndExtra		=0;	 	a->hInstance		=GetModuleHandle(NULL); 	a->hIcon			=NULL; 	a->hCursor			=LoadCursor(NULL, IDC_ARROW);		 	a->hbrBackground	=(HBRUSH)GetStockObject(WHITE_BRUSH); 	a->lpszMenuName		=NULL;	 	a->lpszClassName	=ClassName;	 } ATOM  RegMyClass(  const char* name , WNDPROC  proc) { 	WNDCLASS MyClass; 	SetWNDCLASS ( &MyClass, proc, name ); 	return RegisterClass( &MyClass ); } int main( void ) { 	RegMyClass( "MyClass" , MyProc ); 	CreateWindow( "MyClass" , "绘图" ,WS_OVERLAPPEDWINDOW|WS_VISIBLE,  				300,400,500,500,NULL,NULL,NULL,NULL ); 	MSG msg; 	while( GetMessage( &msg , NULL, 0,0 ) ) 	{ 		DispatchMessage( &msg ); 	} 	return 0; }

user: user-0
content: 引用 8 楼 user-3 的回复:问题在于hdc不能跨消息使用 不是吧，你这样说的话，那个main里的绘图怎么解释？GetDC又怎么解释？ 其实我差不多弄懂是怎么回事了，是ps没有更新，WM_CREATE时窗口大小为0，因此ps里记录的就是{0,0,0,0}，而InvalidateRect使窗口无效化后发送WM_PAINT后，WM_PAINT里也没有更新ps里的矩形，所有绘画不出来，解决办法是把WM_CREATE修改为WM_SIZE，这个时候窗口已经创建完毕，ps可以得到正确的矩形，即便窗口大小变化时也可以正确变化，程序结果也出来了

user: user-3
content: 问题在于hdc不能跨消息使用

user: user-0
content: 在WM_PAINT外一样能用BeginPaint绘图，所以我才会对之前的代码产生疑问  #include "stdio.h" #include "string.h" #include "windows.h" int main( void ) { 	char *str = "C语言";			 	HFONT font = CreateFont( 100, 0, 150, 0, 600, 0, 1, 0, 0, 0, 0, 0, 0, "楷体" );	 	HWND h = GetConsoleWindow(); 	Sleep(100);  	PAINTSTRUCT ps; 	InvalidateRect( h , NULL , 1 );					 	HDC hdc = BeginPaint( h , &ps );			 	SelectObject( hdc , font );					 	TextOut( hdc , 130 , 160 , str , strlen(str) );	 	EndPaint( h , &ps );						 	return 0;  }

user: user-0
content: 引用 1 楼 赵4老师 的回复:BeginPaint The BeginPaint function prepares the specified window for painting and fills a PAINTSTRUCT structure with information about the painting.   HDC BeginPaint(   HWND hwnd,  // handle to window   LPPAINTSTRUCT lpPaint               // pointer to structure for paint information );   Parameters hwnd  Handle to the window to be repainted.  lpPaint  Pointer to the PAINTSTRUCT structure that will receive painting information.  Return Values If the function succeeds, the return value is the handle to a display device context for the specified window.   If the function fails, the return value is NULL, indicating that no display device context is available.   Windows NT: To get extended error information, callGetLastError.  Remarks The BeginPaint function automatically sets the clipping region of the device context to exclude any area outside the update region. The update region is set by the InvalidateRect or InvalidateRgn function and by the system after sizing, moving, creating, scrolling, or any other operation that affects the client area. If the update region is marked for erasing, BeginPaint sends a WM_ERASEBKGND message to the window.   An application should not call BeginPaint except in response to a WM_PAINT message. Each call to BeginPaint must have a corresponding call to the EndPaint function.   If the caret is in the area to be painted, BeginPaint automatically hides the caret to prevent it from being erased.   If the window's class has a background brush, BeginPaint uses that brush to erase the background of the update region before returning.   QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Requires version 1.0 or later.   Header: Declared in winuser.h.   Import Library: Use user32.lib.  See Also Painting and Drawing Overview, Painting and Drawing Functions, EndPaint, InvalidateRect, InvalidateRgn, PAINTSTRUCT, ValidateRect, ValidateRgn 赵老。。。原文我看过的，我想要知道的是为什么不能，而不是应该怎样，我使用InvalidateRect，窗口客户区已无效化，这个时候使用BeginPaint理应可以完成绘图且能显示才对呀

user: user-0
content: 引用 3 楼 Eleven 的回复:你调用BeginPaint应该在WM_PAINT消息响应函数中，而不应该在其它的消息响应中~ 我知道，我只想探究它不能的原因，不使用窗口过程直接在main里使用BeginPaint一样可以完成绘图，我想探究的是它和GetDC的不同究竟在哪里？如何实现完全等效