需求:在窗口中按'b',以黑色绘制曲线,按'r'以红色绘制曲线。默认则以黑色绘制。wm_char中进行选择selectobject, 这个函数有hdc,可是每次执行到wm_paint的时候,wm_paint里获得的dc的值不一样,导致无法绘制。
// test3.cpp : 定义应用程序的入口点。
//#include "stdafx.h"
#include "test3.h"#define MAX_LOADSTRING 100#define TWOPI 2*3.1415#define  NUM 100// 全局变量:
HINSTANCE hInst; // 当前实例
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);int APIENTRY _tWinMain(HINSTANCE hInstance,
   HINSTANCE hPrevInstance,
   LPTSTR    lpCmdLine,
   int       nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此放置代码。
MSG msg;
HACCEL hAccelTable; // 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TEST3, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance); // 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
} hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TEST3)); // 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} return (int) msg.wParam;}LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
static HDC hdc; static HPEN hRedPen; POINT pt[NUM]; RECT rect;
int x,y;
static int cxClient, cyClient; switch (message)
{ case WM_CREATE: hRedPen=CreatePen(PS_SOLID,3,RGB(255,90,33));

break;
case WM_SIZE:
cxClient=LOWORD(lParam);
cyClient=HIWORD(lParam);
break; case WM_CHAR: if(LOWORD(wParam)==_T('r'))   //red
{
SelectObject(hdc,hRedPen);
}
if(LOWORD(wParam)==_T('b'))
{
SelectObject(hdc,GetStockObject(BLACK_BRUSH));
}
GetClientRect(hWnd,&rect);
InvalidateRect(hWnd,&rect,FALSE); break; case WM_COMMAND:
wmId    = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:

hdc = BeginPaint (hWnd, &ps) ;
Rectangle (hdc,    cxClient / 8,     cyClient / 8, 7 * cxClient / 8, 7 * cyClient / 8) ;
Ellipse(hdc,cxClient / 8,     cyClient / 8,7 * cxClient / 8, 7 * cyClient / 8)   ;
MoveToEx(hdc,0,0,NULL); LineTo(hdc,cxClient,cyClient); MoveToEx(hdc,cxClient,0,NULL); LineTo(hdc,0,cyClient); RoundRect(hdc,cxClient/4,cyClient/4,cxClient*3/4,cyClient*3/4,cxClient/4,cyClient/4); EndPaint (hWnd, &ps) ; return 0 ; break;
case WM_DESTROY: DeleteObject(hRedPen); PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

解决方案 »

  1.   

    搞个全局变量,WM_CHAR里改变变量的值,WM_PAINT里根据值Selectobject不同的颜色。还有Selectobject后记得恢复
      

  2.   


    enum PENTYPE{black,red};
    int gSelected=black;现在的问题导致矩形,椭圆等形状全部变黑色,而且按'r'不管用,UpdateWindow根本不会触发wm_paint!!!
    只好换成InvalidRect,什么原因???
    // UpdateWindow(hWnd); GetClientRect(hWnd,&rect); InvalidateRect(hWnd,&rect,TRUE);LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    static HDC hdc; static HPEN hRedPen; POINT pt[NUM]; RECT rect;
    int x,y;
    static int cxClient, cyClient; switch (message)
    { case WM_CREATE: hRedPen=CreatePen(PS_SOLID,3,RGB(255,90,33));

    break;
    case WM_SIZE:
    cxClient=LOWORD(lParam);
    cyClient=HIWORD(lParam);
    break; case WM_CHAR:

    if(LOWORD(wParam)==_T('r'))   //red
     gSelected=red;
    else if(LOWORD(wParam)==_T('b')) //black
    gSelected=black; UpdateWindow(hWnd);
    break; case WM_COMMAND:
    ..............................................................
    break;
    case WM_PAINT:

    hdc = BeginPaint (hWnd, &ps) ; switch(gSelected)
    {
    case black:
    SelectObject(hdc,GetStockObject(BLACK_BRUSH));
    break;
    case red:
      SelectObject(hdc,hRedPen);
    default:
    break;
    }
    Rectangle (hdc,    cxClient / 8,     cyClient / 8, 7 * cxClient / 8, 7 * cyClient / 8) ; Ellipse(hdc,cxClient / 8,     cyClient / 8,7 * cxClient / 8, 7 * cyClient / 8)   ;
    MoveToEx(hdc,0,0,NULL); LineTo(hdc,cxClient,cyClient); MoveToEx(hdc,cxClient,0,NULL); LineTo(hdc,0,cyClient); RoundRect(hdc,cxClient/4,cyClient/4,cxClient*3/4,cyClient*3/4,cxClient/4,cyClient/4); EndPaint (hWnd, &ps) ; return 0 ;
    break;
    case WM_DESTROY: DeleteObject(hRedPen); PostQuitMessage(0);
    break;
    default:
    return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
    }
      

  3.   


    1.换成InvalidateRect后,就可以绘制红色的了,UpdateWindow为什么不行?2.黑色曲线绘制没达到预想的效果,把所有的矩形区域,全部涂成黑色的了。而用红色曲线绘制图形的时候,则是白色填充,红色曲线绘图.2个问题.我应该阐述清楚
      

  4.   

    UpdateWindow的作用是让窗口的无效区域立马刷新,本身不产生无效区域,也就不会触发WM_PAINT,Invalidate/InvaliateRect才是让窗口重绘的,会产生一个WM_PAINT,但是WM_PAINT的消息级别比较低可能不会立马去响应,可能会等多个WM_PAINT累积了才会去,所以可配合UpdateWindow来立即刷新。多调试下
      

  5.   

           case black:
                SelectObject(hdc,GetStockObject(BLACK_BRUSH));
                break;
            case red:
                  SelectObject(hdc,hRedPen);1. 一个是 Pen, 一个是 Brush ?
    2.HBRUSH old =(HBRUSH)SelectObject(hdc,GetStockObject(BLACK_BRUSH));
    用后要恢复:
    SelectObject(hdc,old);
      

  6.   


    UpdateWindow是快速的产生一个wm_paint,迫使case wm_paint被调用按照这个, 那么 case WM_CHAR:
             
            if(LOWORD(wParam)==_T('r'))   //red
                 gSelected=red;
            else if(LOWORD(wParam)==_T('b'))   //black
                gSelected=black;    
     
            UpdateWindow(hWnd);
            break;case wm_paint会被调用的。结果事宜愿为
      

  7.   


    为什么要old?去掉brush导致的错误就2个笔,一个红色,一个黑色。wm_destroy里删除红色的,就可以啊黑色的,是系统管理的吧,想不通,为什么要恢复?
      

  8.   

    UpdateWindow:如果有无效区,则马上sending a WM_PAINT message到窗口处理过程,不进消息队列进行排队等待,立即刷新窗口,否则,什么都不做。 似乎:只有当窗口放到缩小,或者被其他遮挡的时候,区域无效。
    一般是不会无效的,或许这个原因导致,UpdateWindow不管用
      

  9.   


    已经删了啊亲  case WM_DESTROY:
     
            DeleteObject(hRedPen);
     
            PostQuitMessage(0);
            break;
      

  10.   

    gdi对象一旦被select到dc,就归dc所有,直接Delete是删除不了的,所以要把 old 选回去,然后才能 真正把
    pen 删除掉 :
     DeleteObject(hRedPen);
      

  11.   

     case WM_PAINT:             hdc = BeginPaint (hWnd, &ps) ;         switch(gSelected)        {        case black:            hOldPen=SelectObject(hdc,GetStockObject(BLACK_BRUSH));            break;        case red:              SelectObject(hdc,hRedPen);        default:            break;        }case WM_DESTORY:
    SelectObject(hOld);
    DeleteObject(hRedPen);