winapi — C ++ Создание окна в других файлах cpp (не в WinMain)

У меня есть функция, которая находится в другом файле cpp, чем WinMain, и при вызове создаст окно. Однако класс windows для этого нового окна был объявлен и зарегистрирован в WinMain. Теперь, когда я создаю окно в отдельной функции, я вынужден повторно объявить 2-ю и 3-ю переменную функции CreateWindowEx:

_In_opt_  LPCTSTR lpClassName,
_In_opt_  LPCTSTR lpWindowName,

потому что расположение функции, которая фактически создает, не имеет доступа к тем переменным, которые были созданы в WinMain. Теперь … я сомневаюсь, действительно ли моя программа использует класс окна, который я зарегистрировал в WinMain? Насколько я знаю, повторное выделение этих переменных и создание функции вдали от функции WinMain могло привести к тому, что компилятор принял другой стандартный класс окон. Итак, действительно ли моя программа использует класс окна, который я зарегистрировал в WinMain?

Отредактировано: дает немного больше кода

// +++++++++++++++++++++++++++++++++++++ cpp файл с win main:

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

...//previous code made the main window of the program and so forth

const char g_szClassName2[] = "windowClass2";//name of the window class
WNDCLASSEX winClass2;
HWND invisHWnd;

winClass2.cbSize         = sizeof(WNDCLASSEX);
winClass2.style          = 0;
winClass2.lpfnWndProc    = WndProcedure2;
winClass2.cbClsExtra     = 0;
winClass2.cbWndExtra     = 0;
winClass2.hInstance     = hInstance;
winClass2.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
winClass2.hCursor       = LoadCursor(NULL, IDC_ARROW);
winClass2.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
winClass2.lpszMenuName  = NULL;
winClass2.lpszClassName = g_szClassName2;
winClass2.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

RegisterClassEx(&winClass2);

... //other code irrelevant to issue

}

// +++++++++++++++++++++++++++++++++++++ другой файл cpp:

void otherCppFile::creatingWindow()
{

const char g_szClassName2[] = "windowClass2";//name of the window class
const char WndName2[] = "winClass2";//name of the window class

HWND windowHandle = CreateWindowEx(0,
g_szClassName2,
WndName2,
WS_OVERLAPPEDWINDOW,
0,
0,
800,
500,
NULL,
NULL,
NULL,
NULL);
}

Эта последняя функция использует класс окна, зарегистрированный в WinMain, даже если он не находится в WinMain, а некоторые переменные объявлены в функции повторно?

1

Решение

Весь смысл регистрации класс окна это так, что он уникален, и вы можете использовать его, когда вам нужно. Когда вы регистрируете класс окна, используя RegisterClass[Ex] Функция, у вас есть две возможности для ее идентификации:

  • Имя класса окна (строка), которое вы передали в функцию.
  • ATOM (целочисленное значение), которое возвращается функцией.

В 99,9% случаев вы забудете о ATOM и просто используйте строку. Вам нужна строка для Создайте класс окна, так что вы можете просто не отставать от строки и использовать ее для создания окна этого класса.

Технически, то, что вы делаете, это нормально. У вас есть несколько переменных, но все они содержат одно и то же строковое значение, поэтому все работает правильно. Но это кошмар обслуживания, который также нарушает правило СУХОЙ (не повторяйся). Что если вы захотите изменить имя вашего оконного класса? Вам нужно будет найти каждый файл, который объявил его, и убедиться, что вы его обновили. Тогда вам придется вечно ждать, пока весь ваш проект будет перекомпилирован, потому что вы затронули большое количество файлов. Не хорошо.

Вместо этого вы хотите объявить эту переменную в Глобальный объем, делая его доступным в каждом файле вашего проекта, который создает окна. Поместите его в общий заголовочный файл, который вы собираетесь включить во все ваши файлы кода, или создайте отдельный Window.h заголовок или что-то в этом роде и включите его в случае необходимости

Убедитесь, что это имя класса окна объявлено как постоянная. Нет никаких причин, по которым он должен быть изменен во время исполнения вашего приложения.

Если вы боретесь с объявлением и / или использованием глобальных констант в C ++, вы можете проверить ответы на этот вопрос или сделайте свой поиск в переполнении стека. Эта часть не уникальна для программирования Windows; это просто базовый C ++.

Конечно, вы часто будете слышать, что глобальные переменные плохие. Это достаточно верно. Код, который вы пишете, на самом деле не C ++. Это C. Windows API — это C API, поэтому он, естественно, ведет вас к написанию C-кода на C ++. Если вы действительно хотите писать код на C ++, вам нужно найти (или написать свой собственный) оболочку C ++ вокруг Windows API на основе C. Например, вы бы написали класс, который представляет окна, и этот класс содержал бы статическую константу уровня класса, которая содержит имя вашего класса окна. Класс будет отвечать за создание всех новых окон, поэтому вы не будете необходимость разбросать эту информацию или эти детали реализации по нескольким файлам кода.

Насколько имя окна, это совершенно другое. Windows не использует его для идентификации вашего окна. На самом деле, это совершенно необязательный параметр для CreateWindow[Ex] функция. Вам даже не нужно давать окну имя. На самом деле это имя, которое появляется в строке заголовка окна. Используется Пользователь идентифицировать окно. Поэтому его часто нужно локализовать и хранить в файле ресурсов вашего проекта, а не в исходном коде. Использовать LoadString функция загрузить строки из файла ресурсов вашего проекта. Вы можете делать это динамически всякий раз, когда создаете окно: просто загрузите строку, которую вы хотите использовать в качестве заголовка для этого конкретного окна.

2

Другие решения