user-0 提问: 没有设置定时器，为什么还是不断收到WM_TIMER ？

回复:
user: user-0
content: 引用 4 楼 Intel0011 的回复:[quote=引用 3 楼 zgl7903 的回复:] 这个应该是有BUTTON控件为了实现悬停发光等效果启动的定时器吧 可以换其他控件试试看 和控件没有关系，我的测试结果是 在Win10下，如果使用DispatchMessage(&msg);分发消息，则会收到三条WM_TIMER消息，如： GetMessage  ---> 0113 ID=23559 GetMessage  ---> 0113 ID=23560 GetMessage  ---> 0113 ID=1 如果使用 {                typedef LRESULT (CALLBACK *WNDPROC)(HWND, UINT, WPARAM, LPARAM);                WNDPROC lpfnWndProc = (WNDPROC)GetWindowLong(msg.hwnd, GWL_WNDPROC);                CallWindowProc(lpfnWndProc, msg.hwnd, msg.message, msg.wParam, msg.lParam); // 如果不移动窗口，将一直收到WM_TIMER消息 			   } 分发消息，则会一直收到WM_TIMER消息，如： GetMessage  ---> 0113 ID=23525 GetMessage  ---> 0113 ID=23526 GetMessage  ---> 0113 ID=23525 GetMessage  ---> 0113 ID=1 GetMessage  ---> 0113 ID=23525 GetMessage  ---> 0113 ID=23526 GetMessage  ---> 0113 ID=23525 ...... 在XP下，两种方式都只会收到一条WM_TIMER消息，如： GetMessage  ---> 0113 ID=1 不知道系统内部做了什么改变，以及为什么要这样做改变 这里的测试代码如下，各位可以测试看看，欢迎回馈 //* #define UNICODE #define _UNICODE //*/ #include <Windows.h> #include <tchar.h> #include <stdio.h>  #pragma comment(lib, "gdi32.lib") #pragma comment(lib, "user32.lib")  #pragma comment(linker, "/subsystem:console,5.1.2600")  LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);  //int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdLine, int iCmdShow) int main(void) {    static TCHAR szAppName[] = TEXT("HelloWin");    HWND         hwnd;    MSG          msg;    WNDCLASS     wndclass;           RtlZeroMemory(&wndclass, sizeof(wndclass));    wndclass.style         = CS_HREDRAW | CS_VREDRAW;    wndclass.lpfnWndProc   = WndProc;    wndclass.hInstance     = GetModuleHandle(NULL);    wndclass.hIcon         = LoadIcon(NULL, TEXT("#32512"));    wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);    wndclass.lpszMenuName  = NULL;    wndclass.lpszClassName = szAppName;     if (!RegisterClass(&wndclass))    {       MessageBox(NULL, TEXT("This program requires Windows NT series!"), szAppName, MB_ICONERROR);       return -1;    }          hwnd = CreateWindowEx(WS_EX_APPWINDOW,                          szAppName,                  // window class name                          TEXT("The Hello Program"),  // window caption                          WS_OVERLAPPEDWINDOW,        // window style                          500,//CW_USEDEFAULT,              // initial x position                          200,//CW_USEDEFAULT,              // initial y position                          320,//CW_USEDEFAULT,              // initial x size                          320,//CW_USEDEFAULT,              // initial y size                          NULL,                       // parent window handle                          NULL,                       // window menu handle                          GetModuleHandle(NULL),                  // program instance handle                          NULL);                      // creation parameters     ShowWindow(hwnd, SW_SHOW);    UpdateWindow(hwnd);        {       BOOL bRet;       while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)       {          if (msg.message == WM_TIMER) printf("GetMessage  ---> %04X ID=%u\n", msg.message, msg.wParam);          if (bRet == -1)          {             MessageBox(NULL, TEXT("GetMessage Error."), TEXT("Message"), MB_ICONERROR);             return -1;          }          else          {             TranslateMessage(&msg);             #if 01             DispatchMessage(&msg);             #else             {                typedef LRESULT (CALLBACK *WNDPROC)(HWND, UINT, WPARAM, LPARAM);                WNDPROC lpfnWndProc = (WNDPROC)GetWindowLong(msg.hwnd, GWL_WNDPROC);                CallWindowProc(lpfnWndProc, msg.hwnd, msg.message, msg.wParam, msg.lParam); // 如果不移动窗口，将一直收到WM_TIMER消息 			   } 			   #endif          }       }    }     UnregisterClass(szAppName, GetModuleHandle(NULL));    return msg.wParam; }  LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {    //printf("WndProc     ---> %04X\n", message);    switch (message)    {       case WM_DESTROY:          PostQuitMessage(0);          return 0;    }    return DefWindowProc(hwnd, message, wParam, lParam); } [/quote] 老哥，关于这个神秘的WM_TIMER，我最近有点进展，首先我发现这个WM_TIMER不是一直发的，发了十几个就停了，只是因为输出的内容都一样所以一直没发现（不直到是不是后来测试的时候和之前效果不一样了），它在鼠标右移出窗口后会发十几个WM_TIMER消息，但左移、上移不会发，下移不记得了，貌似会；更神奇的事发生了，我最近测试了SetTimer，之后再测试以前的代码的时候，发现效果竟然变了，这个WM_TIMER只发了几次就没发了，再也没像以前那样了，我新建代码文件重新测试，发现效果还是这样。。。你说这个会不会跟SetTimer有关？

user: user-1
content: 线程的所有窗口都共享消息队列，用户代码没有处理的消息，最后都到DefWindowProc那里去了(如果至少一个窗口过程调用了它)，“而且不创建窗口，也不会有该WM_TIMER”这很正常，因为windows不会为线程自动创建消息队列，需要该线程创建第一个窗口才有。

user: user-0
content: 引用 13 楼 早打大打打核战争 的回复:拖动的时候没有WM_TIMER发来很正常，准确地说，不是没有发来，而是GetMessage没提交它，WM_TIMER是低优先级消息，只有消息队列中没有高优先级消息的时候才会post低优先级消息 你的意思是这个WM_TIMER是由GetMessage发出来的？确定吗？

user: user-1
content: 拖动的时候没有WM_TIMER发来很正常，准确地说，不是没有发来，而是GetMessage没提交它，WM_TIMER是低优先级消息，只有消息队列中没有高优先级消息的时候才会post低优先级消息

user: user-0
content: 引用 4 楼 Intel0011 的回复:[quote=引用 3 楼 zgl7903 的回复:] 这个应该是有BUTTON控件为了实现悬停发光等效果启动的定时器吧 可以换其他控件试试看 和控件没有关系，我的测试结果是 在Win10下，如果使用DispatchMessage(&msg);分发消息，则会收到三条WM_TIMER消息，如： GetMessage  ---> 0113 ID=23559 GetMessage  ---> 0113 ID=23560 GetMessage  ---> 0113 ID=1 如果使用 {                typedef LRESULT (CALLBACK *WNDPROC)(HWND, UINT, WPARAM, LPARAM);                WNDPROC lpfnWndProc = (WNDPROC)GetWindowLong(msg.hwnd, GWL_WNDPROC);                CallWindowProc(lpfnWndProc, msg.hwnd, msg.message, msg.wParam, msg.lParam); // 如果不移动窗口，将一直收到WM_TIMER消息 			   } 分发消息，则会一直收到WM_TIMER消息，如： GetMessage  ---> 0113 ID=23525 GetMessage  ---> 0113 ID=23526 GetMessage  ---> 0113 ID=23525 GetMessage  ---> 0113 ID=1 GetMessage  ---> 0113 ID=23525 GetMessage  ---> 0113 ID=23526 GetMessage  ---> 0113 ID=23525 ...... 在XP下，两种方式都只会收到一条WM_TIMER消息，如： GetMessage  ---> 0113 ID=1 不知道系统内部做了什么改变，以及为什么要这样做改变 这里的测试代码如下，各位可以测试看看，欢迎回馈 //* #define UNICODE #define _UNICODE //*/ #include <Windows.h> #include <tchar.h> #include <stdio.h>  #pragma comment(lib, "gdi32.lib") #pragma comment(lib, "user32.lib")  #pragma comment(linker, "/subsystem:console,5.1.2600")  LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);  //int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdLine, int iCmdShow) int main(void) {    static TCHAR szAppName[] = TEXT("HelloWin");    HWND         hwnd;    MSG          msg;    WNDCLASS     wndclass;           RtlZeroMemory(&wndclass, sizeof(wndclass));    wndclass.style         = CS_HREDRAW | CS_VREDRAW;    wndclass.lpfnWndProc   = WndProc;    wndclass.hInstance     = GetModuleHandle(NULL);    wndclass.hIcon         = LoadIcon(NULL, TEXT("#32512"));    wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);    wndclass.lpszMenuName  = NULL;    wndclass.lpszClassName = szAppName;     if (!RegisterClass(&wndclass))    {       MessageBox(NULL, TEXT("This program requires Windows NT series!"), szAppName, MB_ICONERROR);       return -1;    }          hwnd = CreateWindowEx(WS_EX_APPWINDOW,                          szAppName,                  // window class name                          TEXT("The Hello Program"),  // window caption                          WS_OVERLAPPEDWINDOW,        // window style                          500,//CW_USEDEFAULT,              // initial x position                          200,//CW_USEDEFAULT,              // initial y position                          320,//CW_USEDEFAULT,              // initial x size                          320,//CW_USEDEFAULT,              // initial y size                          NULL,                       // parent window handle                          NULL,                       // window menu handle                          GetModuleHandle(NULL),                  // program instance handle                          NULL);                      // creation parameters     ShowWindow(hwnd, SW_SHOW);    UpdateWindow(hwnd);        {       BOOL bRet;       while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)       {          if (msg.message == WM_TIMER) printf("GetMessage  ---> %04X ID=%u\n", msg.message, msg.wParam);          if (bRet == -1)          {             MessageBox(NULL, TEXT("GetMessage Error."), TEXT("Message"), MB_ICONERROR);             return -1;          }          else          {             TranslateMessage(&msg);             #if 01             DispatchMessage(&msg);             #else             {                typedef LRESULT (CALLBACK *WNDPROC)(HWND, UINT, WPARAM, LPARAM);                WNDPROC lpfnWndProc = (WNDPROC)GetWindowLong(msg.hwnd, GWL_WNDPROC);                CallWindowProc(lpfnWndProc, msg.hwnd, msg.message, msg.wParam, msg.lParam); // 如果不移动窗口，将一直收到WM_TIMER消息 			   } 			   #endif          }       }    }     UnregisterClass(szAppName, GetModuleHandle(NULL));    return msg.wParam; }  LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {    //printf("WndProc     ---> %04X\n", message);    switch (message)    {       case WM_DESTROY:          PostQuitMessage(0);          return 0;    }    return DefWindowProc(hwnd, message, wParam, lParam); } [/quote] 的确是拖动的时候没有WM_TIMER发来，你是试出来的还是？ 你是觉得这个WM_TIMER是分发消息或者调用窗口过程产生的？

user: user-2
content: 仅供参考： Message and Message Queue Functions The following functions are used with messages and message queues.        BroadcastSystemMessage   DispatchMessage   GetInputState   GetMessage   GetMessageExtraInfo   GetMessagePos   GetMessageTime   GetQueueStatus   InSendMessage   InSendMessageEx   PeekMessage   PostMessage   PostQuitMessage   PostThreadMessage   RegisterWindowMessage   ReplyMessage   SendAsyncProc   SendMessage   SendMessageCallback   SendMessageTimeout   SendNotifyMessage   SetMessageExtraInfo   TranslateMessage   WaitMessage     Obsolete Functions      PostAppMessage   SetMessageQueue

user: user-0
content: 引用 9 楼 早打大打打核战争 的回复:线程的所有窗口都共享消息队列，用户代码没有处理的消息，最后都到DefWindowProc那里去了(如果至少一个窗口过程调用了它)，“而且不创建窗口，也不会有该WM_TIMER”这很正常，因为windows不会为线程自动创建消息队列，需要该线程创建第一个窗口才有。 这个消息并没有到窗口过程中啊，窗口过程中检测不到，而且消息循环中指定接收某窗口的消息时也不会出现，只有当GetMessage指定窗口为NULL才会接收到，应该能说明是发给线程的。

user: user-3
content: 引用 3 楼 zgl7903 的回复:这个应该是有BUTTON控件为了实现悬停发光等效果启动的定时器吧 可以换其他控件试试看 和控件没有关系，我的测试结果是 在Win10下，如果使用DispatchMessage(&msg);分发消息，则会收到三条WM_TIMER消息，如： GetMessage  ---> 0113 ID=23559 GetMessage  ---> 0113 ID=23560 GetMessage  ---> 0113 ID=1 如果使用 {                typedef LRESULT (CALLBACK *WNDPROC)(HWND, UINT, WPARAM, LPARAM);                WNDPROC lpfnWndProc = (WNDPROC)GetWindowLong(msg.hwnd, GWL_WNDPROC);                CallWindowProc(lpfnWndProc, msg.hwnd, msg.message, msg.wParam, msg.lParam); // 如果不移动窗口，将一直收到WM_TIMER消息 			   } 分发消息，则会一直收到WM_TIMER消息，如： GetMessage  ---> 0113 ID=23525 GetMessage  ---> 0113 ID=23526 GetMessage  ---> 0113 ID=23525 GetMessage  ---> 0113 ID=1 GetMessage  ---> 0113 ID=23525 GetMessage  ---> 0113 ID=23526 GetMessage  ---> 0113 ID=23525 ...... 在XP下，两种方式都只会收到一条WM_TIMER消息，如： GetMessage  ---> 0113 ID=1 不知道系统内部做了什么改变，以及为什么要这样做改变 这里的测试代码如下，各位可以测试看看，欢迎回馈 //* #define UNICODE #define _UNICODE //*/ #include <Windows.h> #include <tchar.h> #include <stdio.h>  #pragma comment(lib, "gdi32.lib") #pragma comment(lib, "user32.lib")  #pragma comment(linker, "/subsystem:console,5.1.2600")  LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);  //int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdLine, int iCmdShow) int main(void) {    static TCHAR szAppName[] = TEXT("HelloWin");    HWND         hwnd;    MSG          msg;    WNDCLASS     wndclass;           RtlZeroMemory(&wndclass, sizeof(wndclass));    wndclass.style         = CS_HREDRAW | CS_VREDRAW;    wndclass.lpfnWndProc   = WndProc;    wndclass.hInstance     = GetModuleHandle(NULL);    wndclass.hIcon         = LoadIcon(NULL, TEXT("#32512"));    wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);    wndclass.lpszMenuName  = NULL;    wndclass.lpszClassName = szAppName;     if (!RegisterClass(&wndclass))    {       MessageBox(NULL, TEXT("This program requires Windows NT series!"), szAppName, MB_ICONERROR);       return -1;    }          hwnd = CreateWindowEx(WS_EX_APPWINDOW,                          szAppName,                  // window class name                          TEXT("The Hello Program"),  // window caption                          WS_OVERLAPPEDWINDOW,        // window style                          500,//CW_USEDEFAULT,              // initial x position                          200,//CW_USEDEFAULT,              // initial y position                          320,//CW_USEDEFAULT,              // initial x size                          320,//CW_USEDEFAULT,              // initial y size                          NULL,                       // parent window handle                          NULL,                       // window menu handle                          GetModuleHandle(NULL),                  // program instance handle                          NULL);                      // creation parameters     ShowWindow(hwnd, SW_SHOW);    UpdateWindow(hwnd);        {       BOOL bRet;       while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)       {          if (msg.message == WM_TIMER) printf("GetMessage  ---> %04X ID=%u\n", msg.message, msg.wParam);          if (bRet == -1)          {             MessageBox(NULL, TEXT("GetMessage Error."), TEXT("Message"), MB_ICONERROR);             return -1;          }          else          {             TranslateMessage(&msg);             #if 01             DispatchMessage(&msg);             #else             {                typedef LRESULT (CALLBACK *WNDPROC)(HWND, UINT, WPARAM, LPARAM);                WNDPROC lpfnWndProc = (WNDPROC)GetWindowLong(msg.hwnd, GWL_WNDPROC);                CallWindowProc(lpfnWndProc, msg.hwnd, msg.message, msg.wParam, msg.lParam); // 如果不移动窗口，将一直收到WM_TIMER消息 			   } 			   #endif          }       }    }     UnregisterClass(szAppName, GetModuleHandle(NULL));    return msg.wParam; }  LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {    //printf("WndProc     ---> %04X\n", message);    switch (message)    {       case WM_DESTROY:          PostQuitMessage(0);          return 0;    }    return DefWindowProc(hwnd, message, wParam, lParam); }

user: user-4
content: 这个应该是有BUTTON控件为了实现悬停发光等效果启动的定时器吧 可以换其他控件试试看

user: user-5
content: 怀疑是windows里会不会有一些进程会对所有进程发送TIMER消息

user: user-2
content: 学会使用Spy++

user: user-0
content: 引用 7 楼 早打大打打核战争 的回复:这个应该是给DefWindowProc用的吧，类似某种keep alive信号，如果应用程序较长时间卡在某段代码，消息循环不能顺畅运转，DefWindowProc没有被调用，Windows就认为该程序运行异常了，弹出应用程序无响应之类的提示 用自注册窗口测试，这个不是发给窗口的，是发给线程的，窗口过程中根本检测不到，GetMessage如果只接收该窗口消息，那么也接收不到这个WM_TIMER，说明这个消息是发给线程的（不可能是发给控制台的吧，发给控制台线程应该接收不到，而且不创建窗口，也不会有该WM_TIMER，说明应该不是发给控制台的）

user: user-1
content: 这个应该是给DefWindowProc用的吧，类似某种keep alive信号，如果应用程序较长时间卡在某段代码，消息循环不能顺畅运转，DefWindowProc没有被调用，Windows就认为该程序运行异常了，弹出应用程序无响应之类的提示

user: user-0
content: 引用 1 楼 赵4老师 的回复:学会使用Spy++ 我这里用的是控制台，消息是发给线程的，我只能取控制台，但spy++检测控制台为特殊窗口，查不了。 而且我想了下，如果创建主窗口，spy++仍然只能检测发到主窗口的消息，而这个是发给线程的消息呀

user: user-0
content: 引用 3 楼 zgl7903 的回复:这个应该是有BUTTON控件为了实现悬停发光等效果启动的定时器吧 可以换其他控件试试看 自己注册的窗口也是一样的，而且这个定时器不是发给窗口的，是发给线程的