InvalidateRect(hwnd, NULL, false);有什么用???

later 2002-12-21 10:06:56
我发现用InvalidateRect(hwnd, NULL, false);和不用此函数的效果差不多啊??
高手解释一下,为什么啊?
如果我用InvalidateRect(hwnd, NULL, true);时,就会发现仅仅移动鼠标它也会不断的重绘绘图去,真是很不爽,哪位解释一下撒
...全文
694 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
NowCan 2002-12-22
  • 打赏
  • 举报
回复
其实一般是不用调用这个函数的。
向你说的移动鼠标也导致重绘,一定是你在MOUSE_MOVE里面调用了这个函数
zswzwy 2002-12-22
  • 打赏
  • 举报
回复
invalidate(false)//擦背景
invalidate(true)//不擦背景

不要放在鼠标移动里
later 2002-12-22
  • 打赏
  • 举报
回复
不用调用这个函数?
我还是不大明白,对了,我这里有一个代码,大家试试看

//====== The Following Program will be used in Computer Graphics course.==========
//============ Designed by Mr. Xiake.610004 =====================
//========================== Sept. 4, 2001 ============================

#include <windows.h>
#include <tchar.H>
#include <math.h>

#define NUM 1000 //You'd better to change it to 10, just test the effect
#define TWOPI (2 * 3.14159)
void line ( HWND hwnd , POINT ptbeg ,POINT ptend);
void floodfill4(int x,int y,COLORREF oldcolor);
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("Hello");
HWND hwnd ;
MSG msg;
WNDCLASS wndclass ;

wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ; // the address of a window procedure used for all
// windows based on the class WNDCLASS
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 ;
//each window class is assigned a name, here is "Hello"

if (!RegisterClass (&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0;
}
hwnd = CreateWindow(szAppName ,
// window class name which is assigned in WNDCLASS object wndclass
TEXT("The Hello Program"),
//window's caption (title name)
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, //initial x position
CW_USEDEFAULT, //initial y position
CW_USEDEFAULT, //initial x size
CW_USEDEFAULT, //initial y size
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd) ;



while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg) ;
DispatchMessage(&msg);
}
return msg.wParam ;
}


LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
static BOOL mm,nn;
static HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
static TCHAR str[100];

static int cxClient, cyClient ; //should be equal to cx and cy
static int min ,MouseDown, dx, dy;

COLORREF crColor;
static int i;
HBRUSH hBrush;
int top;
static POINT mouseb,moused ,ptb, ptd ,apt[2];

switch (message)
{

case WM_CREATE:
// here we can do some initialization jobs.
hdc = GetDC(hwnd); //get the client area the device context
//.... initialize device context attributes
ReleaseDC(hwnd, hdc) ;
return 0 ;

case WM_PAINT:
hdc =BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);

//crColor = RGB(152, 255, 255) ;
// hBrush = CreateSolidBrush(crColor);
// SelectObject (hdc, hBrush);
/*if(i=0; i<(top-1);i++)
{
MoveToEx ( hdc ,apt[i].x ,apt[i].y , NULL);
LineTo ( hdc , apt[i+1].x, apt[i+1].y);
}
if(nn)
{
MoveToEx ( hdc ,apt[0].x ,apt[0].y , NULL);
LineTo ( hdc , apt[top-1].x, apt[top-1].y);

}*/
if( nn)
{ SelectObject (hdc, GetStockObject (BLACK_BRUSH));
line ( hwnd , ptb,ptd);
}
if(mm)
{
SelectObject (hdc, GetStockObject (BLACK_BRUSH));
line ( hwnd , ptb,ptd);

}
DeleteObject(hBrush);


EndPaint(hwnd, &ps);
return 0;

case WM_SIZE:
cxClient = LOWORD(lParam) ;
cyClient = HIWORD(lParam) ;
min = cxClient ;
if (min > cyClient) min = cyClient ;
return 0 ;


return 0 ;
case WM_LBUTTONDOWN:
SetCursor(LoadCursor(NULL ,IDC_CROSS));
mm=TRUE;
//apt[top].x = LOWORD(lParam) ;
//apt[top].y = HIWORD(lParam) ;
//top++;
mouseb.x=moused.x=LOWORD (lParam);
mouseb.y=moused.y=HIWORD (lParam);
line ( hwnd , mouseb ,moused);

return 0;
case WM_MOUSEMOVE:
if(mm)
{
SetCursor(LoadCursor(NULL ,IDC_CROSS));
moused.x=LOWORD(lParam);
moused.y=HIWORD(lParam);
line ( hwnd , mouseb ,moused);
InvalidateRect (hwnd ,NULL, TRUE);
}
return 0;
case WM_LBUTTONUP:
if(mm)

{SetCursor(LoadCursor(NULL ,IDC_ARROW));

mm=false;
nn=true;
ptb=mouseb;
ptd.x=LOWORD(lParam);
ptd.y=HIWORD(lParam);
line ( hwnd , ptb ,ptd);
InvalidateRect (hwnd ,NULL, FALSE);
}
return 0 ;

case WM_KEYDOWN:
switch(wParam)
{
case VK_HOME:
break;
case VK_END:
break;
case VK_PRIOR:
MessageBox(hwnd, TEXT("PageUp key down"),TEXT("键盘"), MB_OK);
break;
case VK_NEXT:
MessageBox(hwnd, TEXT("PageDown key down"),TEXT("键盘"), MB_OK);
break ;
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN:
MessageBox(hwnd, TEXT("Direction key down"),TEXT("键盘"), MB_OK);
break ;
case VK_DELETE:
MessageBox(hwnd, TEXT("Delete key down"),TEXT("键盘"), MB_OK);
break;
}
return 0;
case WM_CHAR:
switch (wParam)
{
case '\b':
MessageBox(hwnd, TEXT("Backspace key down"),TEXT("键盘"), MB_OK);
break;
case 'Q':
case 'q': //Esacpe key
SendMessage(hwnd, WM_CLOSE,0, 0);
}
return 0;

case WM_CLOSE:
if(IDYES == MessageBox(hwnd, TEXT("Do you want to exit?"),
TEXT("Exit Window Hint"),
MB_DEFBUTTON2 | MB_ICONQUESTION | MB_YESNO))
PostQuitMessage(0); //if click yes, then ready to quit the program
return 0; //else, don't quit the program

case WM_DESTROY:
PostQuitMessage(0);
return 0 ;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
void floodfill4(int x,int y,COLORREF oldcolor)
{ HDC hdc;
if( GetPixel(hdc, x, y)==oldcolor )
{SetPixel(hdc, x, y, RGB(200, 100, 100));
floodfill4(x,y+1,oldcolor);
floodfill4(x,y-1,oldcolor);
floodfill4(x-1,y,oldcolor);
floodfill4(x+1,y,oldcolor);
}
}
void line ( HWND hwnd , POINT ptbeg ,POINT ptend)
{
HDC hdc ;
hdc = GetDC ( hwnd );
SelectObject ( hdc ,GetStockObject(NULL_BRUSH));
MoveToEx ( hdc ,ptbeg.x ,ptbeg.y ,NULL);
LineTo ( hdc ,ptend.x ,ptend.y);
ReleaseDC ( hwnd ,hdc );
}
hnyyy 2002-12-21
  • 打赏
  • 举报
回复
这两个都用于声明客户区无效,当下一个WM_PAINT消息到来时发生重画。
其中InvalidateRect(hwnd, NULL, true);重画时将擦除背景。
InvalidateRect(hwnd, NULL, false);重画时不擦除背景。

仅仅移动鼠标它也会不断的重绘?
因为你在WM_MOUSEMOVE消息处理中不断声明无效导致重画。你应该在确实要画或删除些新东西时才声明该区域无效。
实现在窗口中显示按键信息 #include #include //全局变量 RECT rc; //记录滚屏的矩形区域 int xChar, yChar; //文本输入点坐标 WNDCLASSEX wnd; //窗口类结构变量 char szAppName[] = "键盘消息监视程序"; //窗口类名 //函数声名 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); BOOL MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE hInstance,int iCmdShow); //函数:WinMain //作用:入口函数 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR szCmdLine, int iCmdShow) { MSG msg; if(!MyRegisterClass(hInstance)) { return FALSE; } if(!InitInstance(hInstance,iCmdShow)) { return FALSE; } while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } return msg.wParam; } //函数:ShowKey //作用:实现在窗口中显示按键信息 void ShowKey (HWND hwnd, int iType, char *szMessage,WPARAM wParam, LPARAM lParam) { static char *szFormat[2] = { "%-14s %3d %c %6u %4d %5s %5s %6s %6s", "%-14s %3d %c %6u %4d %5s %5s %6s %6s" } ; char szBuffer[80]; HDC hdc; ScrollWindowEx(hwnd, 0, -yChar, &rc, &rc,NULL,NULL,SW_INVALIDATE); hdc = GetDC (hwnd); SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)); TextOut (hdc, xChar, rc.bottom - yChar, szBuffer, wsprintf (szBuffer, szFormat [iType], szMessage, //消息 wParam,//虚拟键代码 (BYTE) (iType ? wParam : ),//显示字符值 LOWORD (lParam),//重复次数 HIWORD (lParam) & 0xFF,//OEM键盘扫描码 //判断是否为增强键盘的扩展键 (PSTR) (0x01000000 & lParam ? "是" : "否"), //判断是否同时使用了ALT键 (PSTR) (0x20000000 & lParam ? "是" : "否"), (PSTR) (0x40000000 & lParam ? "按下" : "抬起"),//判断前一次击键状态 (PSTR) (0x80000000 & lParam ? "按下" : "抬起"))//判断转换状态 ); ReleaseDC (hwnd, hdc); ValidateRect (hwnd, NULL); } //函数:WndProc //作用:处理主窗口的消息 LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { static char szTop[] = "消息 键 字符 重复数 扫描码 扩展码 ALT 前一状态 转换状态"; static char szUnd[] = "_______ __ ____ _____ ______ ______ ___ _______ ______"; //在窗口中输出文字作为信息标题 HDC hdc; PAINTSTRUCT ps; TEXTMETRIC tm; switch (iMsg) { case WM_CREATE://处理窗口创建的消息 hdc = GetDC (hwnd); //设定字体 SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)); //检取当前字体的度量数据 GetTextMetrics (hdc, &tm); xChar = tm.tmAveCharWidth;//保存字体平均宽度 yChar = tm.tmHeight;//保存字体高度 ReleaseDC (hwnd, hdc); rc.top = 3 * yChar / 2; return 0; case WM_SIZE://处理窗口大小改变的消息 //窗体改变后保存新的滚屏区域右下角坐标 rc.right = LOWORD (lParam); rc.bottom = HIWORD (lParam); UpdateWindow (hwnd); return 0; case WM_PAINT://处理窗口重绘消息 InvalidateRect (hwnd, NULL, TRUE); hdc = BeginPaint (hwnd, &ps); SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ; SetBkMode (hdc, TRANSPARENT) ; TextOut (hdc, xChar, yChar / 2, szTop, (sizeof szTop) - 1) ; TextOut (hdc, xChar, yChar / 2, szUnd, (sizeof szUnd) - 1) ; EndPaint (hwnd, &ps); return 0; case WM_KEYDOWN://处理键盘上某一键按下的消息 ShowKey (hwnd, 0, "WM_KEYDOWN", wParam, lParam); return 0; case WM_KEYUP://处理键盘上某一按下键被释放的消息 ShowKey (hwnd, 0, "WM_KEYUP", wParam, lParam); return 0; case WM_CHAR://处理击键过程中产生的非系统键的可见字符消息 ShowKey (hwnd, 1, "WM_CHAR", wParam, lParam); return 0; case WM_DEADCHAR://处理击键过程中产生的非系统键"死字符"消息 ShowKey (hwnd, 1, "WM_DEADCHAR", wParam, lParam); return 0; case WM_SYSKEYDOWN://处理系统键按下的消息 ShowKey (hwnd, 0, "WM_SYSKEYDOWN", wParam, lParam); break; case WM_SYSKEYUP://处理系统键抬起的消息 ShowKey (hwnd, 0, "WM_SYSKEYUP", wParam, lParam); break; case WM_SYSCHAR://处理系统键可见字符消息 ShowKey (hwnd, 1, "WM_SYSCHAR", wParam, lParam); break; case WM_SYSDEADCHAR://处理系统键"死字符"消息 ShowKey (hwnd, 1, "WM_SYSDEADCHAR", wParam, lParam); break; case WM_DESTROY://处理结束应用程序的消息 PostQuitMessage (0); return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam); } //函数:MyRegisterClass //作用:注册窗口类 BOOL MyRegisterClass(HINSTANCE hInstance) { wnd.cbSize= sizeof (wnd); wnd.style = CS_HREDRAW | CS_VREDRAW; wnd.lpfnWndProc = WndProc; wnd.cbClsExtra = 0; wnd.cbWndExtra = 0; wnd.hInstance = hInstance; wnd.hIcon = LoadIcon (NULL, IDI_APPLICATION); wnd.hCursor = LoadCursor (NULL, IDC_ARROW); wnd.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wnd.lpszMenuName = NULL; wnd.lpszClassName = szAppName; wnd.hIconSm = LoadIcon (NULL, IDI_APPLICATION); return RegisterClassEx (&wnd); } //函数:InitInstance //作用:创建主窗口 BOOL InitInstance(HINSTANCE hInstance,int iCmdShow) { HWND hwnd; hwnd = CreateWindow (szAppName, "键盘消息监视程序", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, NULL,NULL,hInstance,NULL ); if(!hwnd) { return FALSE; } ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd); return TRUE; }
主要是模拟初中的物理实验的有源代码,可供初学者使用! 采用 MFC 编制 MVC 模式之球体演示程序 作者:haykey 下载源代码   在传统面向过程的程序设计中,往往采用 Input-Processing-Output 模式,这“归功”于 DOS 操作系统的单任务。当 Windows 图形界面 OS 出现后,MVC(Model-View-Controller)模型更适合 Windows 图形界面程序的设计,它将数据处理和数据显示分离开,使维护,扩展系统更加灵活 。其中,View:负责 显示数据,它从Model处获得数据然后显示。当然,一个Model会有用户可从不同角度来观察的多个View。Model:存储数据以及对数据进行各种运算和处理 。Controller:负责接受用户输入,并且把用户输入转换成对 Model 的操作。因此Controller 可能会修改 Model 的数据,当数据修改后,更新 View。其结构示意图如下:   一直采用MFC编程的朋友可能不太熟悉它,这是因为MFC的文档视图结构就是基于MVC的高层结构,这蒙蔽了我们的双眼。虽然MS替我们做了,我们还是有必要接触它,以在SDK or 其他地方有的放矢。我做了一个球体演示的例子,其界面如下:   左侧两个表面积和体积Edit让使用者从文本的角度精确地观察,我们称其为TextView。右侧为从CStatic派生的CGraphicView,使得人们可直观地观察Sphere.对话窗口CMVCSphereDlg是控制器,来获取用户的键盘输入(输入半径后回车)和在Static上的鼠标点击与拖动(可动态调整球体半径并实时反馈球体变化)而CSphere类是模型,存储了球体半径和计算表面积,计算体积等处理半径数据的操作.   现在让我们详细看看代码,来感受下Model,View,Controller之间如何关联,如何协同工作的。 class CSphere { public: ... .... //更新Graphic-VIEW BOOL UpdateGraphicView(HWND hWnd,const CRect &rect,BOOL bErase); //更新Text-VIEW void UpdateTextView(); //外界Controller的接口:设置球体半径 void SetRadius(float r); private: //球体半径 float m_fRadius; //计算球体表面积 float CalculateArea(float radius); //计算球体体积 float CSphere::CalculateVolumn(float radius); };   这里面 UpdateTextView,UpdateTextView 就是当用户输入新半径或拖动鼠标 Controller 捕获后通知 Model,Model 通知两个View更新显示 。具体代码如下: BOOL CSphere::UpdateGraphicView(HWND hWnd,const CRect &rect,BOOL bErase) { //data format examination if(!::IsWindow(hWnd)||::IsRectEmpty(&rect)) { AfxMessageBox("View is not created by now or rect is empty"); return false; } //get the window pointer from window handle CWnd *pView = CWnd::FromHandle(hWnd); if(pView == NULL) return false; //set graphic view''s radius in order to painting ((CGraphicView*)pView)->SetRadius(m_fRadius); bPaintSphere = true;//set paint tag true //repaint if(!::InvalidateRect(hWnd,&rect,bErase)&& !::UpdateWindow(hWnd)) { AfxMessageBox("UpdateView failed"); return true; } pView = NULL; return false; } void CSphere::UpdateTextView() { CMVCSphereDlg *parent = (CMVCSphereDlg *)AfxGetMainWnd(); CWnd *wnd1 = parent->GetDlgItem(IDC_SURFACE); CWnd *wnd2 = parent->GetDlgItem(IDC_VOLUMN); CString str; str.Format("%.2f平方米",CalculateArea(m_fRadius)); wnd1->SetWindowText(str); str.Empty(); str.Format("%.2f立方米",CalculateVolumn(m_fRadius)); wnd2->SetWindowText(str); } CGraphicView中绘图关键代码如下: void CGraphicView::OnPaint() { ... ..... if(!bPaintSphere) dc.DrawText("球体演示",rect,DT_VCENTER|DT_CENTER|DT_SINGLELINE); else { int r=(int)m_radius;//半径取整 CPoint MiddlePoint = rect.CenterPoint();//以矩形框的中心为球心 int x=MiddlePoint.x; int y=MiddlePoint.y; oldpen = (CPen*)dc.SelectObject(&solid_pen); oldbru = (CBrush*)dc.SelectObject(&brush); dc.Ellipse(x-r,y-r,x+r,y+r); //先画一个圆形 dc.SelectObject(&dash_pen); dc.Arc(x-r/2,y-r,x+r/2,y+r,x,y-r,x,y+r); //再画4个半圆弧 dc.Arc(x-r/2,y-r,x+r/2,y+r,x,y+r,x,y-r); dc.Arc(x-r,y-r/2,x+r,y+r/2,x-r,y,x+r,y); dc.Arc(x-r,y-r/2,x+r,y+r/2,x+r,y,x-r,y); ... ... } } 关于控制器CMVCSphereDlg响应用户输入半径回车核心代码如下: BOOL CMVCSphereDlg::PreTranslateMessage(MSG* pMsg) { UpdateData(); //violation examination if(m_r100) { AfxMessageBox("半径输入范围(0---100)"); return false; } if(pMsg->message == WM_KEYDOWN) if(pMsg->wParam == VK_RETURN)//回车 { CRect rect; m_GraphicView.GetClientRect(rect); m_Sphere.SetRadius(m_r);//把用户输入转换成对Model的操作 m_Sphere.UpdateTextView();//更新View m_Sphere.UpdateGraphicView(m_GraphicView.GetSafeHwnd(),rect,true);//更新View return true; } ... ... } 响应鼠标拖动核心代码如下: void CMVCSphereDlg::OnMouseMove(UINT nFlags, CPoint point) { CRect rect; m_GraphicView.GetClientRect(rect); CPoint middlepoint = rect.CenterPoint(); //if click on the graphic view if(rect.PtInRect(point)&&bIsDragging) { double dbDistance2 = (point.x-middlepoint.x)*(point.x-middlepoint.x)+(point.y-middlepoint.y)*(point.y-middlepoint.y); double dbDistance = sqrt(dbDistance2); if(dbDistance>100.) dbDistance = 100.; m_r = (float)dbDistance; //update radius edit UpdateData(false); m_Sphere.SetRadius(m_r); m_Sphere.UpdateTextView(); m_Sphere.UpdateGraphicView(m_GraphicView.GetSafeHwnd(),rect,true); } ... ... } 该程序功能简单,只是示例性说明采用 MFC 如何实现MVC模型,就当抛砖引玉了。具体实现参考源代码例子。

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧