InvalidateRect 更新无效问题

qq_26540489 2016-07-22 10:02:19
是这样,我在做一个钟表的程序,把钟表的指针用子窗口来刷新,父窗口刷新表盘和中上部文字,其中:drawClock()函数是画表盘; drawHand()函数是画表针;drawLine()是画一条横向的线,画在父子窗口的交界处
PS:这是win32的程序。。。不是MFC

*******************************************************************************************************************/

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

#define ID_TIMER 1
static TCHAR szChild[] = TEXT("test1Child");

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM);
void drawClock(HDC hdc, RECT rect);
void drawHand(HDC hdc, RECT rect);
void drawLine(HDC hdc, int x, int y);

double hour, minute, second;
double tem_h, tem_m, tem_s;
int add_h, add_m, add_s;

HPEN hNewPen_h, hNewPen_m, hNewPen_s, hOldPen;
HPEN hRoll, hBlod;
int mid_y, line_y, mouse_y;
bool isPitch = false;

HWND hwndChild;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("test1");
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))
{
int i = GetLastError();
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);

return 0;
}
wndclass.lpszClassName = szChild;
wndclass.lpfnWndProc = ChildWndProc;
wndclass.cbWndExtra = sizeof(long);
wndclass.hIcon = NULL;
wndclass.hbrBackground = (HBRUSH)GetStockObject(HOLLOW_BRUSH);
RegisterClass(&wndclass);
hwnd = CreateWindow(szAppName,
TEXT("The Hello Program"),
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);
}
return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPARAM)
{
SYSTEMTIME Time = { 0 };
HDC hdc;
PAINTSTRUCT ps;
static RECT rect;
switch (message)
{
case WM_CREATE:
// PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC);
GetLocalTime(&Time);//获得当前本地时间
tem_s = Time.wSecond;
tem_m = Time.wMinute;
tem_h = Time.wHour;
second = Time.wSecond * 2 * 3.14 / 60;
minute = Time.wMinute * 2 * 3.14 / 60 + second / 60;
hour = Time.wHour * 2 * 3.14 / 12 + minute / 60;
add_h = 0;
add_m = 0;
add_s = 0;
hdc = GetDC(hwnd);
GetClientRect(hwnd, &rect);
mid_y = rect.bottom / 2;
line_y = mid_y;

hwndChild = CreateWindow(szChild, NULL, WS_CHILDWINDOW | WS_VISIBLE,rect.left, line_y, rect.right-rect.left, rect.bottom-line_y,hwnd, (HMENU)(001), (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
ReleaseDC(hwnd, hdc);
return 0;
case WM_MOUSEMOVE:
if (isPitch)
{
if (wParam & MK_LBUTTON)
{
line_y = HIWORD(lPARAM);
MoveWindow(hwndChild, 0, line_y, rect.right, rect.bottom-line_y, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
}
}
return 0;
case WM_LBUTTONUP:
InvalidateRect(hwnd, NULL, TRUE);
isPitch = false;
return 0;
case WM_LBUTTONDOWN:
mouse_y = HIWORD(lPARAM);
if ((mouse_y >= line_y - 10) && (mouse_y <= line_y + 40))
{
isPitch = true;
}
InvalidateRect(hwnd, NULL, TRUE);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
rect.bottom = line_y;
DrawText(hdc, TEXT("Hello Word!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
GetClientRect(hwnd, &rect);
drawLine(hdc, rect.right, line_y);
drawClock(hdc, rect);
EndPaint(hwnd, &ps);
return 0;

case WM_DESTROY:
KillTimer(hwnd, ID_TIMER);

DeleteObject(hNewPen_h);
DeleteObject(hNewPen_m);
DeleteObject(hNewPen_s);
DeleteObject(hOldPen);
DeleteObject(hRoll);
DeleteObject(hBlod);
PostQuitMessage(0);
return 0;
default:
break;
}
return DefWindowProc(hwnd, message, wParam, lPARAM);
}

LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
HDC hdc;
PAINTSTRUCT ps;
static RECT rect;

switch (message)
{
case WM_CREATE:
SetTimer(hwnd, ID_TIMER, 1000, NULL);
return 0;

case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
drawHand(hdc, rect);
EndPaint(hwnd, &ps);
return 0;
case WM_TIMER:
add_s++;
if (add_s == 60)
{
add_m++;
add_s = 0;
}
if (add_m == 60)
{
add_h++;
add_m = 0;
}if (add_h == 12)
add_h = 0;
second = (tem_s + add_s) * 2 * 3.14 / 60;
minute = (tem_m + add_m) * 2 * 3.14 / 60 + second / 60;
hour = (tem_h + add_h) * 2 * 3.14 / 12 + minute / 60;
InvalidateRect(hwnd, NULL, TRUE);
return 0;
default:
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}

void drawClock(HDC hdc, RECT rect)
{
hBlod = CreatePen(PS_SOLID, 3, RGB(30, 30, 30));
double tem_s;
int point_x, point_y, r;
int h_x, h_y;
if (rect.right>(rect.bottom - line_y))
{
r = (rect.bottom - line_y)*0.4;
}
else
{
r = rect.right * 0.4;
}
point_x = rect.right / 2;
point_y = (rect.bottom - line_y) / 2 + line_y;

hOldPen = (HPEN)SelectObject(hdc, hBlod);
Ellipse(hdc, point_x - r, point_y - r, point_x + r, point_y + r);
for (int i = 0; i<12; i++)
{
if (i == 0 || i == 3 || i == 6 || i == 9)
{

tem_s = i*3.14 * 2 / 12;
h_x = sin(tem_s)*r;
h_y = cos(tem_s)*r;
MoveToEx(hdc, h_x + point_x, h_y + point_y, NULL);
h_x = sin(tem_s)*(r*0.75);
h_y = cos(tem_s)*(r*0.75);
LineTo(hdc, h_x + point_x, h_y + point_y);
continue;
}
tem_s = i*3.14 * 2 / 12;
h_x = sin(tem_s)*r;
h_y = cos(tem_s)*r;
MoveToEx(hdc, h_x + point_x, h_y + point_y, NULL);
h_x = sin(tem_s)*(r*0.9);
h_y = cos(tem_s)*(r*0.9);
LineTo(hdc, h_x + point_x, h_y + point_y);
}
}

void drawHand(HDC hdc, RECT rect)
{
hNewPen_h = CreatePen(PS_SOLID, 8, RGB(50, 70, 83));
hNewPen_m = CreatePen(PS_SOLID, 4, RGB(192, 192, 192));
hNewPen_s = CreatePen(PS_SOLID, 1, RGB(118, 128, 105));
int hx, hy, mx, my, sx, sy;
int point_x, point_y, r;
if (rect.right>(rect.bottom - rect.top))
{
r = (rect.bottom - rect.top)*0.4;
}
else
{
r = rect.right * 0.4;
}
point_x = rect.right / 2;
point_y = (rect.bottom - rect.top) / 2 ;
MoveToEx(hdc, point_x, point_y, NULL);
hx = sin(hour)*(r / 5);
hy = -cos(hour)*(r / 5);
mx = sin(minute)*(r / 2);
my = -cos(minute)*(r / 2);
sx = sin(second)*r;
sy = -cos(second)*r;

hOldPen = (HPEN)SelectObject(hdc, hNewPen_h);
LineTo(hdc, hx + point_x, hy + point_y);

SelectObject(hdc, hNewPen_m);
MoveToEx(hdc, point_x, point_y, NULL);
LineTo(hdc, mx + point_x, my + point_y);

SelectObject(hdc, hNewPen_s);
MoveToEx(hdc, point_x, point_y, NULL);
LineTo(hdc, sx + point_x, sy + point_y);

SelectObject(hdc, hOldPen);
}

void drawLine(HDC hdc, int x, int y)
{
HPEN hNewPen, hOldPen;
hNewPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
hOldPen = (HPEN)SelectObject(hdc, hNewPen);
MoveToEx(hdc, 0, y, NULL);
LineTo(hdc, x, y);
SelectObject(hdc, hOldPen);
DeleteObject(hNewPen);
}

现在问题如下:子视窗新的表针不断地再画但是之前旧的表针还存在着,而计时器WM_TIMMER中也写了可是不起作用
怀疑可能导致的因素:
(1) UpdateWindow(hwnd);只在主函数写了,更新的是父窗口的句柄,是不是写个子窗口的更新,可是写在哪里?父窗口的WM_CREATE?
( 2 ) InvalidateRect(hwnd, NULL, TRUE);中的hwnd是子窗口的形参,真的实参我不大清楚在哪里赋值的,会不会是这个句柄是父窗口的句柄导致一直更新的是父窗口,但是修改哪里呢?
(3) 虽然可能性不大,但是不会是需要多线程来轮流调度父子窗口吧
...全文
150 7 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
schlafenhamster 2016-07-23
  • 打赏
  • 举报
回复

// 不使用 SetROP2(hdc,R2_NOT); 的
void drawHand(HDC hdc, RECT rect,BOOL erase)
{
	if(erase)
	{// 背景色 白色
		hNewPen_h = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
		hNewPen_m = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
		hNewPen_s = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
	}
	else
	{
		hNewPen_h = CreatePen(PS_SOLID, 8, RGB(50, 70, 83));
		hNewPen_m = CreatePen(PS_SOLID, 4, RGB(192, 192, 192));
		hNewPen_s = CreatePen(PS_SOLID, 1, RGB(118, 128, 105));
	}
	int hx, hy, mx, my, sx, sy;
	int point_x, point_y, r;
	if (rect.right>(rect.bottom - rect.top))
	{
		r = (int)((rect.bottom - rect.top)*0.4);
	}
	else
	{
		r = (int)(rect.right * 0.4);
	}
	point_x = rect.right / 2;
	point_y = (rect.bottom - rect.top) / 2 ;
	hx = (int)(sin(hour)*(r / 5));
	hy = (int)(-cos(hour)*(r / 5));

	mx = (int)(sin(minute)*(r / 2));
	my = (int)(-cos(minute)*(r / 2));

	sx = (int)(sin(second)*r);
	sy = (int)(-cos(second)*r);

	hOldPen = (HPEN)SelectObject(hdc, hNewPen_h);
	MoveToEx(hdc, point_x, point_y, NULL);
	LineTo(hdc, hx + point_x, hy + point_y);

	SelectObject(hdc, hNewPen_m);
	MoveToEx(hdc, point_x, point_y, NULL);
	LineTo(hdc, mx + point_x, my + point_y);

	SelectObject(hdc, hNewPen_s);
	MoveToEx(hdc, point_x, point_y, NULL);
	LineTo(hdc, sx + point_x, sy + point_y);

	SelectObject(hdc, hOldPen);
}
schlafenhamster 2016-07-22
  • 打赏
  • 举报
回复
1. void drawHand(HDC hdc, RECT rect) { SetROP2(hdc,R2_NOT); 2. 画2次 case WM_TIMER: // 擦除 原来的 hdc=GetDC(hwnd); GetClientRect(hwnd, &rect); drawHand(hdc, rect); // 改变时间 add_s++; if (add_s == 60) { add_m++; add_s = 0; } if (add_m == 60) { add_h++; add_m = 0; }if (add_h == 12) add_h = 0; second = (tem_s + add_s) * 2 * 3.14 / 60; minute = (tem_m + add_m) * 2 * 3.14 / 60 + second / 60; hour = (tem_h + add_h) * 2 * 3.14 / 12 + minute / 60; // 画新的 hdc=GetDC(hwnd); GetClientRect(hwnd, &rect); drawHand(hdc, rect); // InvalidateRect(hwnd, NULL, TRUE); return 0;
qq_26540489 2016-07-22
  • 打赏
  • 举报
回复
引用 2 楼 VisualEleven 的回复:
InvalidateRect(hwnd, NULL, TRUE); ---》 InvalidateRect(GetParent(hwnd), NULL, TRUE);
您好,这样是可以的,但是不就是没有了子视窗的意义了嘛。我做子视窗是想只刷新子视窗的东西,不用连带父视窗一起重绘
qq_26540489 2016-07-22
  • 打赏
  • 举报
回复
引用 1 楼 lx624909677 的回复:
InvalidateRect的调用里,rect呢?
为空的话不是就刷新整个客户区么。。?
lx624909677 2016-07-22
  • 打赏
  • 举报
回复
BOOL InvalidateRect( HWND hWnd, // handle of window with changed update region CONST RECT *lpRect, // address of rectangle coordinates BOOL bErase // erase-background flag ); 第二个参数表示要重绘的区域坐标,如果调用不好用,试试Invalidate(TRUE);如果这个可以,那就是坐标计算错了
Eleven 2016-07-22
  • 打赏
  • 举报
回复
InvalidateRect(hwnd, NULL, TRUE); ---》 InvalidateRect(GetParent(hwnd), NULL, TRUE);
lx624909677 2016-07-22
  • 打赏
  • 举报
回复
InvalidateRect的调用里,rect呢?

15,980

社区成员

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

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