使用定时器回调函数出现问题

梦之领域 2013-03-09 06:30:39
用一个窗口类创建了两个窗口,然后在消息处理程序中的 WM_CREATE 中创建了两个定时器,两个定时器间隔均 3 秒,两个 TimerProc 的功能是将各自相关的窗口颜色由红变蓝,再由蓝变红,如些反复。不同的是要求一个窗口为蓝时另一个为红。

问题:基本上总是一个窗口固定为蓝色,而另一个窗口固定为红色,没有出现“明显变换”现象(变换是有的,但都是眨眼即过,按理说均有三秒的停留时间,不明白这是为什么)

// 定时器#2(使用定时器回调函数)

#include <windows.h>

UINT_PTR ID1,ID2;
HWND hwnd1,hwnd2 ;

// 定时器回调函数
VOID CALLBACK TimerProc1 (HWND, UINT, UINT, DWORD ) ;
VOID CALLBACK TimerProc2 (HWND, UINT, UINT, DWORD ) ;
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("Beeper2") ;

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 ("程序需要 Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}

hwnd1 = CreateWindow (szAppName, TEXT ("定时器演示#2-1"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;

ShowWindow (hwnd1, iCmdShow) ;
UpdateWindow (hwnd1) ;

hwnd2 = CreateWindow (szAppName, TEXT ("定时器演示#2-2"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;

ShowWindow (hwnd2, iCmdShow) ;
UpdateWindow (hwnd2) ;

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


LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

switch (message)
{
case WM_CREATE: // 设置定时器
ID1 = SetTimer (NULL, 0, 3000, TimerProc1) ;
ID2 = SetTimer (NULL, 0, 3000, TimerProc2);
return 0 ;


case WM_DESTROY : // 停止定时器
KillTimer (hwnd1, ID1) ;
KillTimer (hwnd2, ID2) ;
PostQuitMessage (0) ;

return 0 ;
}

return DefWindowProc (hwnd, message, wParam, lParam) ;
}

// 定时器回调函数
VOID CALLBACK TimerProc1 (HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime)
{
static BOOL fFlipFlop = FALSE ;

HBRUSH hBrush ;
HDC hdc ;
RECT rc ;

MessageBeep (-1) ;
fFlipFlop = !fFlipFlop ;
GetClientRect (hwnd1, &rc) ;

hdc = GetDC (hwnd1) ;
hBrush = CreateSolidBrush (fFlipFlop ? RGB(255,0,0) : RGB(0,0,255)) ;

FillRect (hdc, &rc, hBrush) ;
ReleaseDC (hwnd1, hdc) ;
DeleteObject (hBrush) ;
}

VOID CALLBACK TimerProc2 (HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime)
{
static BOOL TWO = TRUE ;

HBRUSH hBrush ;
HDC hdc ;
RECT rc ;

MessageBeep (-1) ;
TWO = !TWO ;
GetClientRect (hwnd2, &rc) ;

hdc = GetDC (hwnd2) ;
hBrush = CreateSolidBrush (TWO ? RGB(255,0,0) : RGB(0,0,255)) ;

FillRect (hdc, &rc, hBrush) ;
ReleaseDC (hwnd2, hdc) ;
DeleteObject (hBrush) ;
}


运行截图:



应该是每过三秒上面的窗口和下面的窗口颜色就对换一次,可是现在上面的窗口始终是红色,下面的窗口始终是蓝色,(有变换,但都是眨一下即过,程序原意是每个状态要保持三秒,三秒一次切换,不应该这么快呀)
...全文
462 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
夫人的泡泡鱼 2013-03-10
  • 打赏
  • 举报
回复
学习了,版主......
菜牛 2013-03-09
  • 打赏
  • 举报
回复
正好吃完饭没事干:
// 全局变量:
BOOL bFlip = FALSE;
int nTimerId = 1;
HWND hWnd1 = NULL;
HWND hWnd2 = NULL;
HBRUSH brush[2];

void CALLBACK TimerProc(HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime)
{
	bFlip = !bFlip;
	if (hWnd1){
		InvalidateRect(hWnd1, NULL, TRUE);
	}
	if (hWnd2){
		InvalidateRect(hWnd2, NULL, TRUE);
	}
}

//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的: 处理主窗口的消息。
//
//  WM_COMMAND	- 处理应用程序菜单
//  WM_PAINT	- 绘制主窗口
//  WM_DESTROY	- 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)
	{
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO: 在此添加任意绘图代码...
		if (hWnd == hWnd1){
			FillRect(ps.hdc, &ps.rcPaint, brush[bFlip]);
		}
		else
		{
			FillRect(ps.hdc, &ps.rcPaint, brush[!bFlip]);
		}
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
					   _In_opt_ HINSTANCE hPrevInstance,
					   _In_ LPTSTR    lpCmdLine,
					   _In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

	TCHAR szWindowClass[] = _T("MyWindowClass");			// 主窗口类名

	//  目的: 注册窗口类。
	WNDCLASSEX wcex;
	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32PROJECT1));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= NULL;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
	RegisterClassEx(&wcex);

	hWnd1 = CreateWindow(szWindowClass, _T("窗口一"), WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

	hWnd2 = CreateWindow(szWindowClass, _T("窗口二"), WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

	brush[0] = CreateSolidBrush(RGB(255, 0, 0));
	brush[1] = CreateSolidBrush(RGB(0, 0, 255));

	if (!hWnd1 || !hWnd2 || !brush[0] || !brush[1])
	{
		return FALSE;
	}

	ShowWindow(hWnd1, nCmdShow);
	UpdateWindow(hWnd1);

	ShowWindow(hWnd2, nCmdShow);
	UpdateWindow(hWnd2);

	SetTimer(NULL, nTimerId, 3000, TimerProc);

	// 主消息循环:
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	hWnd1 = NULL;
	hWnd2 = NULL;

	DeleteObject(brush[0]);
	brush[0] = NULL;
	DeleteObject(brush[1]);
	brush[1] = NULL;

	return (int) msg.wParam;
}
菜牛 2013-03-09
  • 打赏
  • 举报
回复
我知道原因了,你只需要一个定时器就行了,现在两个窗口各自创建一个定时器,还是在互相修改。
菜牛 2013-03-09
  • 打赏
  • 举报
回复
不明白还有什么一样,如果你说过渡效果你本来就没有设计,如果说变色应该是没有问题的。但是,你这种绘制方式有问题,应该是在定时器中修改变量,刷新窗口,窗口WM_PAINT消息中根据控制变量重绘。 话说已经好几年没搞Win32了,但是你的代码还有几处问题,是不是关闭一个窗口另外一个也关了?回调函数中你创建了两次画刷却只销毁一次,存在GDI资源泄漏。
梦之领域 2013-03-09
  • 打赏
  • 举报
回复
引用 1 楼 Mackz 的回复:
你的程序每个窗口都创建了两个定时器!
请问,为什么我这么改写了函数,情况还是和原来一样?
// 定时器#2(使用定时器回调函数)

#include <windows.h>

UINT_PTR     ID; 
HWND         hwnd1,hwnd2 ;

// 定时器回调函数
VOID  CALLBACK TimerProc (HWND, UINT, UINT,   DWORD ) ;

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT ("Beeper2") ;
    
    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 ("程序需要 Windows NT!"), 
                    szAppName, MB_ICONERROR) ;
        return 0 ;
    }
     
	hwnd1 = CreateWindow (szAppName, TEXT ("定时器演示#2-1"),
                         WS_OVERLAPPEDWINDOW,
                         CW_USEDEFAULT, CW_USEDEFAULT,
                         CW_USEDEFAULT, CW_USEDEFAULT,
                         NULL, NULL, hInstance, NULL) ;
     
    ShowWindow (hwnd1, iCmdShow) ;
    UpdateWindow (hwnd1) ;

	hwnd2 = CreateWindow (szAppName, TEXT ("定时器演示#2-2"),
                         WS_OVERLAPPEDWINDOW,
                         CW_USEDEFAULT, CW_USEDEFAULT,
                         CW_USEDEFAULT, CW_USEDEFAULT,
                         NULL, NULL, hInstance, NULL) ;
     
    ShowWindow (hwnd2, iCmdShow) ;
    UpdateWindow (hwnd2) ;
     
    while (GetMessage (&msg, NULL, 0, 0))
    {
        TranslateMessage (&msg) ;
        DispatchMessage (&msg) ;
    }
    return msg.wParam ;
}


LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 
    switch (message)
    {
    case   WM_CREATE: // 设置定时器
           ID = SetTimer (NULL, 0, 3000, TimerProc) ;
           return 0 ;


    case   WM_DESTROY : // 停止定时器
           KillTimer (hwnd1, ID) ;
           PostQuitMessage (0) ;

           return 0 ;
    }

    return DefWindowProc (hwnd, message, wParam, lParam) ;
}

// 定时器回调函数
VOID CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime)
{
    static BOOL fFlipFlop = FALSE ;	
        
    HBRUSH  hBrush ;
    HDC     hdc ;
    RECT    rc ;

    MessageBeep (-1) ;
    fFlipFlop = !fFlipFlop ;  

    GetClientRect (hwnd1, &rc) ;
	hdc = GetDC (hwnd1) ;
    hBrush = CreateSolidBrush (fFlipFlop ? RGB(255,0,0) : RGB(0,0,255)) ;
    FillRect (hdc, &rc, hBrush) ;
    ReleaseDC (hwnd1, hdc) ;


	GetClientRect (hwnd2, &rc);
	hdc = GetDC (hwnd2) ;
    hBrush = CreateSolidBrush ( fFlipFlop ? RGB(0,0,255) : RGB(255,0,0)) ;
    FillRect (hdc, &rc, hBrush) ;
    ReleaseDC (hwnd2, hdc) ;

    
    DeleteObject (hBrush) ;
}

梦之领域 2013-03-09
  • 打赏
  • 举报
回复
引用 1 楼 Mackz 的回复:
你的程序每个窗口都创建了两个定时器!
引用 2 楼 zqckzqck 的回复:
两个窗口同时用了一个注册类和同一个窗口函数,
多谢二位。
夫人的泡泡鱼 2013-03-09
  • 打赏
  • 举报
回复
两个窗口同时用了一个注册类和同一个窗口函数,
菜牛 2013-03-09
  • 打赏
  • 举报
回复
你的程序每个窗口都创建了两个定时器!

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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