WinApi任务查杀

时间:2016-04-26 17:00:28

标签: c++ winapi task

我有超级简单的WinApi程序。关闭按钮不会破坏程序的进程。应该添加什么?

#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>


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

HINSTANCE hINSTANCE;

int WINAPI WinMain(HINSTANCE hInstance,
               HINSTANCE hPrevInstance,
               LPSTR lpstr,
               int nCmdShow) {

// VARIABLES
    TCHAR className[] = _T("win32api");
    TCHAR windowName[] = _T("Protected Window");

    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(NULL, IDI_INFORMATION);
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = className;
    wcex.hIconSm = LoadIcon(NULL, IDI_SHIELD);

    if (!RegisterClassEx(&wcex)) {
        MessageBox(NULL, _T("Cannot register window"), _T("Error"), MB_OK | MB_ICONERROR);
        return 0;
    }

     HWND hWnd = CreateWindow(className,
                              windowName,
                              WS_OVERLAPPEDWINDOW,
                              CW_USEDEFAULT,
                              CW_USEDEFAULT,
                              300,
                              300,
                              NULL,
                              NULL,
                              hInstance,
                              NULL);

    if (!hWnd) {
        MessageBox(hWnd, _T("Call to register windows isn't working"), _T("Error"), NULL);
        return 1;
    }

    hINSTANCE = hInstance;
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    MSG msg;

    while (GetMessage(&msg, hWnd, 0, 0) != 0 || GetMessage(&msg, hWnd, 0, 0) != -1) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.lParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uInt, WPARAM wParam, LPARAM lParam) {
    PAINTSTRUCT ps;
    HDC hdc;
    switch (uInt) {
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        TextOut(hdc, 10, 20, _T("Text sample right here boyz."), _tcsclen(_T("Text sample right here boyz.")));
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, uInt, wParam, lParam);
        break;
    }

    return 0;
}

如果我再添加一个案例

case WM_CLOSE:
    PostQuitMessage(0);
    break;

它根本没有关闭(按下关闭按钮没有做任何事情)。非常感谢任何其他提示。

2 个答案:

答案 0 :(得分:4)

您的消息循环错误,原因有两个:

  1. 您正在拨打GetMessage()两次。不要那样做!想想如果你这样做会发生什么。如果GetMessage()左侧的||调用要检测WM_QUIT(它不能,请参见下文),则会返回0.这会导致{|| 1}}调用右侧的GetMessage(),忽略前一次调用的WM_QUIT并阻止循环,直到稍后有新消息到达。您应该在每次循环迭代时只调用GetMessage()一次,然后根据需要对返回值执行操作:

    BOOL bRet;
    
    do
    { 
        bRet = GetMessage(&msg, hWnd, 0, 0);
        if (bRet == 0) break;
        if (bRet == -1)
        {
            // handle the error and possibly exit
        }
        else
        {
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
        }
    }
    while (1);
    
  2. 但是,您还要按HWNDdon't do that!)过滤邮件,因此它只会通过{{1}返回发布到指定HWND的邮件}。 PostMessage()PostQuitMessage()消息发布到调用线程本身的输入队列,而不是WM_QUIT。因此,过滤永远不会看到HWND消息。为了让WM_QUIT打破循环,您需要完全停止WM_QUIT过滤,或者至少定期进行未过滤的调用。

  3. 您的消息循环应该是这样的。这是标准消息循环:

    HWND

    请注意,there is no need to handle -1 from GetMessage()!

答案 1 :(得分:0)

要关闭应用程序,您需要销毁窗口。通常,这是通过以下两种方式之一完成的:

  1. WM_CLOSE处理程序调用{​​{1}}。
  2. DestroyWindow处理完您所做的事后的消息。
  3. 你的DefWindowProc有点不同寻常。我通常把它们写成:

    WndProc

    有关{ switch(msg) { case WM_CLOSE: // prompt user, clean stuff up, etc. break; case WM_DESTROY: PostQuitMessage(0); break; // Other cases here. Most will fall out of the switch so that // DefWindowProc can handle them (for other system notifications). // Only return from the case if you really don't want anybody else // to handle the message. } return DefWindowProcW(hwnd, msg, wParam, lParam); } 的详细信息,请参阅https://msdn.microsoft.com/en-us/library/windows/desktop/ms632617(v=vs.85).aspx,其中明确说明您必须致电WM_CLOSE或让DestroyWindow执行此操作。