Проблема в том, что вы компилируете свой проект для ANSI, где TCHAR
является псевдонимом для CHAR
, и, таким образом, создаете ListBox на основе ANSI, но вы отправляете в него строки 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;
}
Как говорится, вы смешиваете API ANSI, Unicode и TCHAR
. Вам нужно выбрать стиль 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);
}
Иначе, используйте Юникод для всего:
#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);
}