C ++ WinAPI。列表框中显示错误的文本

时间:2018-05-11 16:56:43

标签: c++ winapi sendmessage

我有一项任务是创建一个程序,显示系统中所有窗口的描述符列表。我得到了这个输出:

image

也许编码错误?

这是我的代码:

#include <windows.h>

ATOM RegMyWindowClass(HINSTANCE, LPCTSTR);
HWND hListBox;
HINSTANCE hin;

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    WCHAR str[255];
    if (GetWindowTextW(hwnd, str, 255)) {
        if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER)))
            SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
    }
    return 1;
}

LRESULT CALLBACK WndProc(
    HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_LBUTTONUP:
        MessageBox(hWnd, TEXT("Вы кликнули!"), TEXT("событие"), 0);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);  
        break;
    case WM_CREATE:
        hListBox = CreateWindow("LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL,
            0, 0, 400, 400, hWnd, (HMENU)1111, hin, NULL);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance,
    HINSTANCE         hPrevInstance,
    LPSTR             lpCmdLine,
    int               nCmdShow)
{
    LPCTSTR lpzClass = TEXT("My Window Class!");

    if (!RegMyWindowClass(hInstance, lpzClass))
        return 1;

    RECT screen_rect;
    GetWindowRect(GetDesktopWindow(), &screen_rect); 
    int x = screen_rect.right / 2 - 200;
    int y = screen_rect.bottom / 2 - 200;

    HWND hWnd = CreateWindow(lpzClass, TEXT("Window"),
        WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, 400, 400, NULL, NULL,
        hInstance, NULL);
    ShowWindow(hWnd, SW_SHOW);
    EnumWindows(&EnumWindowsProc, 0);
    if (!hWnd) return 2;

    MSG msg = { 0 };   
    int iGetOk = 0;   
    while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0)
    {
        if (iGetOk == -1) return 3;  
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;  
}

ATOM RegMyWindowClass(HINSTANCE hInst, LPCTSTR lpzClassName)
{
    WNDCLASS wcWindowClass = { 0 };
    wcWindowClass.lpfnWndProc = (WNDPROC)WndProc;
    wcWindowClass.style = CS_HREDRAW | CS_VREDRAW;
    wcWindowClass.hInstance = hInst;
    wcWindowClass.lpszClassName = lpzClassName;
    wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
    return RegisterClass(&wcWindowClass); 
}

任何想法如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

问题是您正在为ANSI编译项目,其中TCHARCHAR的别名,因此正在创建基于ANSI的ListBox,但您要向其发送Unicode字符串。这就是你在输出中看到垃圾的原因。您需要将ANSI字符串发送到ListBox,例如:

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER)))
        CHAR str[255] = {};
        if (GetWindowTextA(hwnd, str, 255)) {
            SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
        }
    }
    return TRUE;
}

可替换地:

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER))) {
        CHAR str[255] = {};
        if (IsWindowUnicode(hwnd)) {
            WCHAR wstr[255] = {}; 
            int len = GetWindowTextW(hwnd, wstr, 255);
            if (len) {
                len = WideCharToMultiByte(CP_ACP, 0, wstr, len+1, str, 255, NULL, NULL);
            }
            if (!len) {
                return TRUE;
            }
        }
        else if (!GetWindowTextA(hwnd, str, 255)) {
            return TRUE;
        }
        SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
    }
    return TRUE;
}

话虽如此,您正在混合使用ANSI,Unicode和TCHAR API。您需要选择 1 API样式并坚持使用它,不要混用它们(除非您绝对必须这样做)。

由于您展示的大多数代码已经在使用TCHAR,因此您可以使用TCHAR作为所有内容(但是,您真的不应该这样做,因为TCHAR是用于向后兼容Win9x / ME,没人使用,仅用于帮助人们将代码迁移到Unicode。现代代码根本不应该使用TCHAR

#include <windows.h>

ATOM RegMyWindowClass(HINSTANCE, LPCTSTR);
HWND hListBox;
HINSTANCE hin;

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER))) {
        TCHAR str[255];
        if (GetWindowText(hwnd, str, 255)) {
            SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
        }
    }
    return TRUE;
}

LRESULT CALLBACK WndProc(
    HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_LBUTTONUP:
        // this is one case where it doesn't make sense to use TCHAR
        MessageBoxW(hWnd, L"Вы кликнули!", L"событие", 0);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);  
        break;
    case WM_CREATE:
        hListBox = CreateWindow(TEXT("LISTBOX"), TEXT(""), WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL,
            0, 0, 400, 400, hWnd, (HMENU)1111, hin, NULL);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance,
    HINSTANCE         hPrevInstance,
    LPSTR             lpCmdLine,
    int               nCmdShow)
{
    LPCTSTR lpzClass = TEXT("My Window Class!");

    if (!RegMyWindowClass(hInstance, lpzClass))
        return 1;

    RECT screen_rect;
    GetWindowRect(GetDesktopWindow(), &screen_rect); 
    int x = screen_rect.right / 2 - 200;
    int y = screen_rect.bottom / 2 - 200;

    HWND hWnd = CreateWindow(lpzClass, TEXT("Window"),
        WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, 400, 400, NULL, NULL,
        hInstance, NULL);
    ShowWindow(hWnd, SW_SHOW);
    EnumWindows(&EnumWindowsProc, 0);
    if (!hWnd) return 2;

    MSG msg = { 0 };   
    int iGetOk = 0;   
    while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0)
    {
        if (iGetOk == -1) return 3;  
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;  
}

ATOM RegMyWindowClass(HINSTANCE hInst, LPCTSTR lpzClassName)
{
    WNDCLASS wcWindowClass = { 0 };
    wcWindowClass.lpfnWndProc = &WndProc;
    wcWindowClass.style = CS_HREDRAW | CS_VREDRAW;
    wcWindowClass.hInstance = hInst;
    wcWindowClass.lpszClassName = lpzClassName;
    wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
    return RegisterClass(&wcWindowClass); 
}

其他,将Unicode用于所有内容:

#include <windows.h>

ATOM RegMyWindowClass(HINSTANCE, LPCWSTR);
HWND hListBox;
HINSTANCE hin;

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER))) {
        WCHAR str[255];
        if (GetWindowTextW(hwnd, str, 255)) {
            SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
        }
    }
    return TRUE;
}

LRESULT CALLBACK WndProc(
    HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_LBUTTONUP:
        MessageBoxW(hWnd, L"Вы кликнули!", L"событие", 0);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);  
        break;
    case WM_CREATE:
        hListBox = CreateWindowW(L"LISTBOX", L"", WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL,
            0, 0, 400, 400, hWnd, (HMENU)1111, hin, NULL);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance,
    HINSTANCE         hPrevInstance,
    LPSTR             lpCmdLine,
    int               nCmdShow)
{
    LPCWSTR lpzClass = L"My Window Class!";

    if (!RegMyWindowClass(hInstance, lpzClass))
        return 1;

    RECT screen_rect;
    GetWindowRect(GetDesktopWindow(), &screen_rect); 
    int x = screen_rect.right / 2 - 200;
    int y = screen_rect.bottom / 2 - 200;

    HWND hWnd = CreateWindowW(lpzClass, L"Window",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, 400, 400, NULL, NULL,
        hInstance, NULL);
    ShowWindow(hWnd, SW_SHOW);
    EnumWindows(&EnumWindowsProc, 0);
    if (!hWnd) return 2;

    MSG msg = { 0 };   
    int iGetOk = 0;   
    while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0)
    {
        if (iGetOk == -1) return 3;  
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;  
}

ATOM RegMyWindowClass(HINSTANCE hInst, LPCWSTR lpzClassName)
{
    WNDCLASSW wcWindowClass = { 0 };
    wcWindowClass.lpfnWndProc = &WndProc;
    wcWindowClass.style = CS_HREDRAW | CS_VREDRAW;
    wcWindowClass.hInstance = hInst;
    wcWindowClass.lpszClassName = lpzClassName;
    wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
    return RegisterClassW(&wcWindowClass); 
}

或者,如果您需要保持与项目中其他地方的现有代码逻辑的兼容性,请坚持使用ANSI:

#include <windows.h>

ATOM RegMyWindowClass(HINSTANCE, LPCSTR);
HWND hListBox;
HINSTANCE hin;

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER))) {
        CHAR str[255];
        if (GetWindowTextA(hwnd, str, 255)) {
            SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
        }
    }
    return TRUE;
}

LRESULT CALLBACK WndProc(
    HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_LBUTTONUP:
        // this is one case where it doesn't make sense to use ANSI
        MessageBoxW(hWnd, L"Вы кликнули!", L"событие", 0);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);  
        break;
    case WM_CREATE:
        hListBox = CreateWindowA("LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL,
            0, 0, 400, 400, hWnd, (HMENU)1111, hin, NULL);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance,
    HINSTANCE         hPrevInstance,
    LPSTR             lpCmdLine,
    int               nCmdShow)
{
    LPCSTR lpzClass = "My Window Class!";

    if (!RegMyWindowClass(hInstance, lpzClass))
        return 1;

    RECT screen_rect;
    GetWindowRect(GetDesktopWindow(), &screen_rect); 
    int x = screen_rect.right / 2 - 200;
    int y = screen_rect.bottom / 2 - 200;

    HWND hWnd = CreateWindowA(lpzClass, "Window",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, 400, 400, NULL, NULL,
        hInstance, NULL);
    ShowWindow(hWnd, SW_SHOW);
    EnumWindows(&EnumWindowsProc, 0);
    if (!hWnd) return 2;

    MSG msg = { 0 };   
    int iGetOk = 0;   
    while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0)
    {
        if (iGetOk == -1) return 3;  
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;  
}

ATOM RegMyWindowClass(HINSTANCE hInst, LPCSTR lpzClassName)
{
    WNDCLASSA wcWindowClass = { 0 };
    wcWindowClass.lpfnWndProc = &WndProc;
    wcWindowClass.style = CS_HREDRAW | CS_VREDRAW;
    wcWindowClass.hInstance = hInst;
    wcWindowClass.lpszClassName = lpzClassName;
    wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
    return RegisterClassA(&wcWindowClass); 
}