Пустое окно на win api

Простой пример создания окна с помощью win api на си — win forms

Primary tabs

Forums:

Разберём здесь базовый пример. позже выложу более подробные комментарии кода.

  • Log in to post comments
  • 7646 reads

Thu, 10/13/2011 — 13:31

А теперь расмотрим конкретый

А теперь расмотрим конкретый пример использования winapi для получения простейшего пользовательского интерфейса —
окна с кнопкой, по нажатии на которую «вываливается » сообщение. (код на языке си) =

_____________
матфак вгу и остальная классика =)

Окно пустое, если подкласс для управления EDIT в C++ WINAPI

У меня есть элемент управления EDIT, который я пытаюсь подклассы, и когда я делаю это, все окно пуст:

Я просто не могу понять, почему все окно пуст при вызове SetWindowLongPtr

Под «пустым» вы подразумеваете, что он не отображается на экране?

Если да, это потому, что, когда вы подклассифицируете Окно, все его сообщения будут отправлены в новый MessageProc, который не имеет всех функций, чтобы правильно отображать его в нем по умолчанию функция Proc (например, WM_PAINT или даже щелчок на кнопке).

Поэтому вам нужно что-то вроде этого:

Это вызовет надлежащие WM_PAINT и другие сообщения в messageProc, который отвечает за рисование и щелчок и другие функции (DefWindowProc() в подклассе).

В качестве альтернативы вы также можете просто внедрить WM_PAINT в свой NewMessageProc для всех ваших подклассов, но не вызывая их DefWindowProc, вам нужно будет сделать для каждого события, которое они могут получить (mousemove, щелчки мыши, щелчки кнопок, все), поэтому используя их оригинальные DefWindowProc проще.

Окно сообщений в приложении Windows без окна

У меня есть приложение, которое я хочу запустить в фоновом режиме без видимых окон или консолей. Для этого я создаю приложение Windows, но я не создаю окно. Приложению необходимо выполнить некоторую очистку по запросу, чтобы закрыть (то есть, когда пользователь выходит из системы). Как я могу определить, когда закрыть? Могу ли я просто создать цикл сообщений, который обрабатывает сообщение WM_CLOSE? Но тогда у меня нет WndProc для обработки сообщения WM_CLOSE.

c++ windows winapi

3 ответа

2 Решение Remus Rusanu [2013-09-18 10:45:00]

Чтобы создать приложение, работающее в фоновом режиме, создайте службу. Служба может отвечать на вызовы ServiceMain .

Если вы настаиваете на крепировании приложения на передней панели, в основном нет никаких законных причин, по которым приложения пытаются скрыть свое главное окно. Исполняемое изображение может быть либо графическим интерфейсом ( IMAGE_SUBSYSTEM_WINDOWS_GUI ), либо консолью ( IMAGE_SUBSYSTEM_WINDOWS_CUI ), и вы не можете их смешивать, см. Как написать программу, которая может запускаться либо как консоль, либо графическое приложение. Если вы выберете GUI-приложение, тогда вы должны создать насос сообщений. Вы можете создать скрытое окно в качестве основного окна. Вы получите WM_QUERYENDSESSION и WM_ENDSESSION в этом скрытое окно (это сообщения, которые вас интересуют, а не WM_CLOSE ).

С другой стороны, консольное приложение должно будет обрабатывать сигналы, например, Andon уже показал вам.

Выберите яд. Я настоятельно рекомендую пройти маршрут обслуживания, так же как и подходящий путь для приложения «background».

Не беспокойтесь о создании фиктивного окна, есть гораздо более простой способ обработки событий закрытия/выхода в приложении без окон. Для этого вы используете малоизвестную функцию Win API, называемую SetConsoleCtrlHandler (. )

Вот пример использования Control Handler:

Мне нужно было узнать об этом пару лет назад, потому что некоторое среднее изделие не правильно очищало свои ресурсы, когда мое консольное приложение было завершено с помощью Ctrl + C . Я обнаружил это случайно, когда смотрел на трассировку стека. Стоит отметить, что это отменяет стандартный обработчик сигнала для таких событий, как Ctrl + C .

Кстати, хотя он называется «Консоль управления обработчиком», он отлично работает в приложениях, которые используют WinMain (. ) вместо main (. ) .

  • Создайте окно, но не устанавливайте флаг WS_VISIBLE.
  • Создайте окно только для сообщений.

Разница заключалась бы в том, что невидимые окна получают широковещательные сообщения, а окна с сообщениями — нет.

проблема с Win API, не отображается окно

просьба сильно ногами не бить, я только учусь=)
проблема следующая, код компилируется, запускается и ничего.

висит в процессах, дебаг показал что прога ждёт отклика от GetMessage(&msg,0,0,0), как и должно быть.

вопрос, почему не отображается окошко на экране?

и в каких случаях регистрация окна (т.е. RegisterClassEx()) не происходит?(был трабл с регистрацией, но я что то поменял и он пропал, но что забыл:confused:)

п.с. среда VS2005 Professional

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
<
HDC hDC;
PAINTSTRUCT PaintSt;
RECT aRect;
switch(message)
<
case(WM_PAINT):
hDC = BeginPaint(hWnd,&PaintSt);
GetClientRect(hWnd,&aRect);
SetBkMode(hDC, TRANSPARENT);
DrawText(hDC,L»Это ТеХт, денег не дам!»,-1,&aRect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
EndPaint(hWnd,&PaintSt);
return 0;
case(WM_DESTROY):
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hWnd,message,wParam,lParam);
>
return 0;
>

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
<
WNDCLASSEX wcex;
HWND hWnd;
MSG msg;

wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpsz ;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

hWnd = CreateWindow(L»OFWin»,L»My First Window»,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,0,hInstance,0);
hWnd = CreateWindow(L»xXx»,L»wWw»,WS_VISIBLE,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,0,0,hInstance,0);

Пустое окно на win api

В этом посте мне хочется рассказать, как создать простейшее приложение с использованием WinAPI и языка программирования C++. Обычное, пустое окошко Windows. Причины, побудившие меня к этому, очень просты: источники, которые я читал до определенного момента не давали мне полного представления о том, что и как работает в приложении Win32. Понимать я это стал, как ни удивительно, только после того, как тот же материал был освещен на лекциях в универе. Почему-то в том виде, в каком преподносилась информация на лекциях, она лучше откладывалась в памяти, нежели “книжные” записи, пусть даже совсем неплохие. Еще одно обстоятельство, способствовавшее идее освящения данной темы – желание лучше закрепить материал, излагая его в письменной форме и, возможно, даже расширить свои знания, заглянув лишний раз в MSDN, чтобы дополнить что-то.

Как, думаю, стало понятно из вступления, материал этого поста и, вероятно, последующих постов на тему WinAPI и программирования под ОС Windows будут основываться на универских лекциях + MSDN с добавлением чего-то от себя (по делу :)).

Наверное, в начале стоит сказать, что Windows API (Application Programming Interface) – это набор готовых классов, функций, структур и констант, при помощи которых любое приложение может взаимодействовать с операционной системой (ОС) Windows.

Также отмечу, что основные функции Windows API появились еще в Win16 и с каждой версией Windows их набор расширяется, утрачивая, однако, при этом поддержку некоторых других функций. Схематично, это можно представить так:

Итак, для любого Windows приложения требуется написать как минимум 2 функции:
Точка входа в приложение, в которой необходимо:

  1. зарегистрировать класс окна
  2. создать окно
  3. запустить цикл обработки сообщений

Win API. Как сделать прозрачное окно?

Я
Илон Маск рекомендует:  Как в Word убрать фон текста
Супер король

Пишу прогу на MS Visual Studio под Win32, не консольную.
Создается простое окно.
Нужно чтобы оно было прозрачным, с видимой нарисованной сеткой. Чтобы можно было это окно наложить поверх другой программы.

И еще нужно чтобы окно не было активным и не перехватывало события мыши. Чтобы кликалась другая программа.

Как такое сделать? Или это нельзя сделать?

Супер король Супер король

CreateRectRgn
CombineRgn
SetWindowRgn

Супер король

А если я попаду мышью в сетку, то событие получит это окно? А надо чтобы оно не получало ничего, как будто сетки нет.

Супер король Супер король H A D G E H O G s Супер король

(16) Ок. Куплю коту Вискас.

Кирпич, если использовать то что в (10) посоветовали, то вырезать квадратики из окна не нужно будет? Можно сделать окно прозрачным, нарисовать в окне то что нужно не прозрачным цветом, и прикрутить (10)? Или это сложнее чем с регионами делать?

Супер король Супер король H A D G E H O G s H A D G E H O G s

In a window currently covered by another window in the same thread (the message will be sent to underlying windows in the same thread until one of them returns a code that is not HTTRANSPARENT).

Я проверил.
Работает для 2-х форм одного процесса, не работает для 2-х форм различных процессов.

H A D G E H O G s

AttachThreadInput()
но тут у нас гемморойчик — надо узнать PID потока (ну пусть будет дескриптор окна) — подложки — а это перебор Z- ордера top level окон, поиск в нем нашего покрывающего окна и полученение предыдущего окна — подложки.

А чего — полупрозрачные окна не решают проблему ?
Окно с дыркой выглядит как-то не очень.

Если нужно просто изображение другого окна в своём как-то отслеживать, то можно не прозрачное окно сделать, а прозрачный фон — тогда мышь будет ездить по нашему окну, а видеть мы будем то, что было до появления нашего окна.

Пустое окно на win api

регистрация класса окна

  • у каждого окна есть оконная процедура, которая обрабатывает сообщения
  • все окна в пределах одного класса имеют одну общую оконную процедуру
  • и прежде чем создавать окно некоторого класса процесс обязан зарегистрировать этот лкасс
  • за регистрацию класса отвечает функция
  • ATOM WINAPI RegisterClassEx( const WNDCLASSEX *lpwcx );
  • struct WNDCLASSEX < UINT cbSize; // размер структуры UINT style; // стиль класса WNDPROC lpfnWndProc; // указатель на оконную процедуру int cbClsExtra; // кол-во байт которые надо аллоцировать для window-class structure (доп память, доступная всем окнам класса) int cbWndExtra; // кол-во байт которые надо аллоцировать для window-instace(доп память, своя у каждого окна) HINSTANCE hInstance; // хэндл к сущности содержащей оконную процедуру HICON hIcon; // хэндл к иконке HCURSOR hCursor; // хэндл к курсору HBRUSH hbrBackground; // хэндл к кисточке или значение цвета (ВАЖНО не удалять кисточку до закрытия приложения) LPCTSTR lpszMenuName; // имя ресурса-меню LPCTSTR lpszClassName; // строчка или ATOM (созданный предыдущим вызовом RegisterClassEx) HICON hIconSm; // хэндл для маленькой иконки >
  • BOOL WINAPI UnregisterClass( LPCTSTR lpClassName, // имя класса или ATOM HINSTANCE hInstance ) // хэндл к модулю, создавшему класс
    • ВАЖНО: до вызова этой функции надо уничтожить все окна этого класса
  • ПРИМЕЧАНИЕ: классы зарегистрированные в DLL не анрегистрируются при выгрузке DLL из приложения
  • стили класса окна
    • там могут параметры типа CS_CLASSDC, что означает один DC на все окна этого класса (обратное — CS_OWNDC)
    • CS_DBLCLKS — отсылать сообщение о двойных кликах
    • CS_DROPSHADOW — эффект «тени» у окон этого класса
    • CS_GLOBALCLASS — зарегистрировать как глобальный класс
    • CS_(V)HREDRAW — перерисовка при смещении/растяжении по горизонтали(вертикали)
  • оконная процедура
    • LRESULT CALLBACK MainWndProc( HWND hwnd, // handle to window UINT uMsg, // message identifier WPARAM wParam, // first message parameter LPARAM lParam) // second message parameter

типы классов: локальные, глобальные, системные

  • глобальные классы приложения
    • классы зарегестрированные в Exe или Dll и доступные ВСЕМ модулям этого процесса.
    • задается стилем CS_GLOBALCLASS
  • локальные классы приложения
    • регистрируется чтобы только .DLL и .EXE зарегистрировавшие его могли им пользоваться
    • обычно такие делают в одном экземпляре
    • для пояснение, зарегистрировав в DllMain локальный класс окна, для того, чтобы его вызвать, неолбходимо в параметре hInstance передать описатель .dll файла
  • системные классы
    • зарегистрированы системой, большинство из них доступны для использования всеми процессами
    • процессы не могут Unregister их
    • доступные пользователю классы
      • Button, ComboBox, Edit, ListBox, MDIClient, ScrollBar, Static
    • каждый процесс получает свою копию системных классов
    • система регистрирует их для процесса при первом вызове GDI функции из какого-либо потока процесса
  • совсем уж глобальные классы
    • через реестр можно добавить свою dll, регистрирующую класс окна, в список тех, которые подгружаются в КАЖДОМ процессе.
  • HWND WINAPI CreateWindowEx( );
  • притом отправляются сообщения (в таком порядке)
    • WM_NCCREATE
      • создание неклиентской части
      • должно вернуть TRUE
    • WM_CREATE
      • создано окно, еще не показано
      • должно вернуть 0
    • у обоих
      • wParam not used
      • lParam — казатель на CREATESTRUCT — структура хранящая все данные из CreateWindowEx
  • стили
    • WS_CHILD(WINDOW) — дочернее ли окно
    • WS_BORDER — отобаржать ли гранциы окна
    • WS_CLIPCHILDREN — не перерисовывать детей при перерисовке родителя
    • MAXIMIZE, OVERLAPPED, SYSMENU, SIZEBOX etc.
  • расширенные стили
    • WS_EX_ACCEPTFILES возможность принимать фалйы drag & drop’ом
    • WS_EX_OVERLAPPEDWINDOW — создает overlapped окно
    • WS_EX_LAYERED — создает layered окно
    • WS_EX_TOPMOST — окно с повышенным приоритетом в z-order
    • различные работы с границами (отображать кграницу окна, клиентской зоны и т.д.)
    • скроллбары, окна-палитры, контекстная подсказка в заглоловке, работу с панелью задач (WS_EX_APPWNIDOW)
  • top-level окно
    • окно, у которого нет родителей (или родитель — рабочий стол)
  • overlapped
    • top-level окно, создается сразу с заголовком, границами и клиентской чстью. Также может иметь скроллы, меню, minimize-maximize кнопки
    • обычно используется для главного окна приложения
  • popup
    • подвид overlapped окон, отличие — у него может не быть заголовка
    • обычно используется для диалогов, сообщений и других временных окон
  • child
    • обязательно имеет лишь клиентскую область, и при создании ОБЯЗАТЕЛЬНО указывать окно-родителя
      • родителем может быть popup, overlapped или child окно
    • может имтеь заголовок, меню,
    • обитает в клиентской зоне родительского окна
  • layered
    • понтовые визуальные эффекты игры с прозрачностью/затемненностью, удобын тем что при перерисовке он вваегда перерисовывает окна которые находятся под layered.
    • можно сделать top-level -> layered при помощи SetWindowLong или WS_EX_LAYERED (с Windows8 можно сделать layered child window )
    • SetLayeredWindowAttributes — настройка параметров
      • настройка, какие именно цвета будут прозрачными
        • для этого используется COLORREF // на самом деле это просто переопределенный DWORD
      • настройка самой прозрачности
  • message-only
    • используется только для получения/отправки сообщений, невидимо, не получает массово-расслыаемых сообщений (broadcast), просто перерабатывает сообщения
    • для создания такого окна надо в кач-ве hWndParent передать описатель HWND_MESSAGE или другое message-only окно

иерархия окон (child/parent owner/owned)

  • child/parent
    • пункт выше
  • owner/owned
    • иерархия появляется, когда не определен WS_CHILD, но указано дочернее окно
    • правила
      • owned окно всегда спереди своего owner’а
      • owned разрушается при разрушении owner’a
      • owned сворачивается при соворачивании owner’a
    • GetWindow( handle, GW_OWNER ) — функция для вытаскивания описателя owner’a
      • там также можно вытаскивать любые другие окнна в порядке Z-order
    • owner’ами могут быть только overlapped и pop-up окна
  • воображаемая ось, идушая от экрана к пользователю, чем выше координата окна на ней, тем больше других окон оно перекрывает
  • child’ы сгруппированы со своими родителями в этом порядке
  • на самом верху располгаются topmost окна, которые в z-order обязательно выше чем все сотальные типы окон (top-level например)
  • позиция окна меняется функциями
    • BringWindowToTop( handle )
Илон Маск рекомендует:  Как в PowerPoint пронумеровать слайды

изменеие положения и размеров окна

  • функция MoveWindow( HWND, x, y, w, h, repaint )
    • WM_WINDOWPOSCHANGING
      • wParam не используется
      • lParam — указатель на WINDOWPOS (новое положение)
    • WM_WINDOWPOSCHANGED
      • параметры см выше
    • WM_MOVE
      • wParam not used
      • lParam — левый верхний угол
    • WM_SIZE
      • wParam флаг, означающий как было изменен размер окна
      • lParam — размер клиентской части
      • тип запроса (минимайз/максимайз/рестор/для поп-апов)
    • WM_PAINT // если repaint — true
      • параметры не используются
  • foreground окно — окно с которым пользователем в данный момент работает (хреновое определение с msdn), поток, который это окно обрабатывает — foreground thread ( более простое обхяснение — САМОЕ ВЫСОКОЕ В Z-ORDER’е )
  • оно одно в каждый момент времени и достается при помощи GetForegroundWindow
  • его можно менять при помощи SetForegroundWindow, но это можно сделать лишь при одном из этих случаев (ограничения на ВЫЗЫВАЮЩИЙ процесс)
    • процесс щас foreground
    • процесс был запущен foreground процессом
    • процесс получил последний input event
    • нету foreground процесса в системе
    • foreground процесс в дебаггинге
    • foreground is not locked( LockSetForegroundWindow() )
    • foreground lock закончился
    • нету активных меню
  • если пользователь работает в дочернем окне, то foreground — окно родитель этого ребенка
  • если активация переключается между окнами РАЗНЫХ приложений
    • WM_ACTIVATEAPP
      • wParam
        • true если активируется, false если деактивируется
      • lParam
        • если wParam true, то это Id потока, чье окно дезактивируется
        • ———- false——————————- активируется
  • если активация переключается между окнами ОДНОГО приложения
    • WM_ACTIVATE
      • wParam
        • указывает, окно деактивируется, активируется просто или кликом
      • lParam
        • хэндл другого окна (в зависимости от значения wParam оно дез или актив.)
  • окно, которое перехватывает input с клавиатуры
  • тут для понимания необходимо помнить, что все виджеты — это системные окна
  • WM_KILLFOCUS
    • wParam — окно получившее фокус
    • lParam — не используется
  • WM_SETFOCUS
    • wParam — окно у которого отобрали фокус
    • lParam — не исп.
  • сначал WM_CLOSE (например при нажатии кнопки закрыть)
    • параметры не используются
    • тут можно показать всякие «вы уверены?»
  • затем вызвыают DestroyWindow
  • затем шлется WM_DESTROY
    • параметры не используются
    • отсылается когда окно убрано с экрана, сначала шлется родителю (когда придет очередь до убийства детей — пошлется и им)
    • родителю шлется еще до того, как дети будут уничтожаться
  • затем шлется WM_NCDESTROY
    • параметры не используются
    • шлется после того, как всех детей перебьют
    • тут уже можно высвобождать какую-либо память выделенная для этого окна и его детишек, все, кому она должна была потребоваться, уже убиты
  • WM_(H)VSCROLL
    • wParam — флаг, обозначающий, пользователь щас держит скроллбар, или только-только отпустить, сдвинут до конца, сдвинут на линию, сдвинут на страницу
    • lParam — если сообщение отослано некоторым контролом — хэндл контрола
  • int ScrollWindowEx(, In const RECT *prcScroll, // позволяет скроллить часть клиентской области );

Пустое окно на win api

В этом тутоpиале мы изучим дочеpние элементы упpавления (child window controls), котоpые являются важными частями ввода и вывода нашей пpогpаммы.

Windows пpедоставляет несколько пpедопpеделенных классов окон, котоpые мы можем сpазу же использовать в своих пpогpаммах. Как пpавило, мы будем использовать их как компоненты dialog box’ов, поэтому они носят название дочеpних элементов упpавления. Эти элементы обpабатывают сообщения от клавиатуpы и мыши и уведомляют pодительское окно, если их состояние изменяется. Они снимают с пpогpаммистов огpомный гpуз, поэтому вам следует использовать их так часто, как это возможно. В этом тутоpиале, я положу их на обычное окно, только для того, чтобы пpодемонстpиpовать как их можно создать и использовать, но в pеальности вам лучше класть их на dialog box.

Пpимеpами пpодопpеделенных классов окон являются кнопки, списки, сheckbox’ы, pадиокнопки и т.д.

Чтобы использовать дочеpнее окно, вы должны создать его с помощью функции CreateWindow или CreateWindowEx. Заметьте, что вы не должны pегистpиpовать класс окна, так как он уже был заpегистpиpован Windows. Имя класса окна должно быть именем пpедопpеделенного класса. Скажем, если вы хотите создать кнопку, вы должны указать «button» в качестве имени класса в CreateWindowsEx. Дpугие паpаметpы, котоpые вы должны указать — это хэндл pодительского окна и ID контpола. ID контpола должно быть уникальным. Вы используете его для того, чтобы отличать данный контpол от дpугих.

После того, как контpол был создан, он посылает сообщение, уведомляющие pодительское окно об изменении своего состояния. Обычно вы создаете дочеpнее окно во вpемя обpаботки сообщения WM_CREATE главного окна. Дочеpнее окно посылает сообщение WM_COMMAND pодительскому окну со своим ID в нижнем слове WParam’а, код уведомления в веpхнем слове wParam’а, а ее хэндл в lParam’е. Каждое окно имеет pазные коды уведомления, свеpьтесь с вашим спpавочником по Win32 API, чтобы получить подpобную инфоpмацию.

Родительское окно также может посылать команды дочеpним окнам, вызывая функцию SendMessage. Функция SendMessage посылает опpеделенные сообщения с сопутствующими значениями в wParam и lParam окну, чей хэндл пеpедается функции. Это очень полезная функция, так как она может посылать сообщения любому окну, хэндл котоpого у вас есть.

Поэтому, после создания дочеpних окон, pодительское окно должно обpабатывать сообщения WM_COMMAND, чтобы быть способным получать коды уведомления от дочеpних окон.

Мы создадим окно, котоpое содеpжит edit-контpол и pushbutton. Когда вы нажмете на кнопку, появится окно, отобpажающее текст, введеный в edit box’е. Также имеется меню с 4 пунктами:

  1. Say Hello — ввести текстовую стpоку в edit box
  2. Clear Edit Box — очистить содеpжимое edit box’а
  3. Get Text — отобpазить окно с текстом в edit box’е
  4. Exit — закpыть пpогpамму

Давайте пpоанализиpуем пpогpамму.

Мы создаем контpолы во вpемя обpаботки сообщения WM_CREATE. Мы вызываем CreateWindowEx с дополнительным стилем, из-за чего клиентская область выглядит вдавленной. Имя каждого контpола пpедопpеделенно — «edit» для edit-контpола, «button» для кнопки. Затем мы указываем стили дочеpних окон. У каждого контpола есть дополнительные стили, кpоме обычные стилей окно. Hапpимеp, стили кнопок начинаются с «BS_», стили edit’а — с «ES_». Вы должны посмотpеть инфоpмацию об этих стилях в вашем спpавочнике по Win32 API. Заметьте, что вместо хэндла меню вы пеpедаете ID контpола. Это не вызывает никаких пpотивоpечй, поскольку дочеpний элемент упpавления не может иметь меню. После создания каждого контpола, мы сохpаняем его хэндл в соответствующей пеpеменной для будущего использования.

SetFocus вызывается для того, чтобы напpавить фокус ввода на edit box, чтобы пользователь мог сpазу начать вводить в него текст.

Обpатите внимание, что меню тоже шлем сообщение WM_COMMAND, чтобы уведомить окно о своем состоянии. Как мы можем пpовести pазличие между сообщениями WM_COMMAND, исходящими от меню и контpолов? Вот ответ:

Нижнее слово wParam Верхнее слово wParam lParam
ID меню
ID контрола Код уведомления Хэндл дочернего окна

Вы можете видеть, что вы должны пpовеpить lParam. Если он pавен нулю, текущее сообщение WM_COMMAND было послано меню. Вы не можете использовать wParam, чтобы pазличать меню и контpол, так как ID меню и ID контpола могут быть идентичными и код уведомления должен быть pавен нулю.

Вы можете поместить текстовую стpоку в edit box с помощью вызова SetWindowText. Вы очищаете содеpжимое edit box’а с помощью вызова SetWindowText, пеpедавая ей NULL. SetWindowText — это функция общего назначения. Вы можете использовать ее, чтобы изменить заголовок окна или текст на кнопке. Чтобы получить текст в edit box’е, вы можете использовать GetWindowText.

Пpиведенный выше кусок кода является обpаботкой нажатия на кнопку. Сначала он пpовеpяет нижнее слово wParam’а, чтобы убедиться, что ID контpола пpинадлежит кнопке. Если это так, он пpовеpяет веpхнее слово wParam’а, чтобы убедиться, что был послан код уведомления BN_CLICKED, то есть кнопка была нажата.

Илон Маск рекомендует:  Онлайн-интенсив «Базовый HTML и CSS» с личным наставником

После этого идет собственно обpаботка нажатия на клавиш. Мы хотим получить текст из edit box’а и отобpазить его в message box’е. Мы можем пpодублиpовать код в секции IDM_GETTEXT выше, но это не имеет смысла. Если мы сможем каким-либо обpазом послать сообщение WM_COMMAND с нижним словом wParam, содеpжащим значение IDM_GETTEXT нашей пpоцедуpе окна, то избежим дублиpования кода и упpостим пpогpамму. Функция SendMessage — это ответ. Эта функция посылает любое сообщение любому окну с любым wParam’ом и lParam’ом, котоpые нам понадобятся. Поэтому вместо дублиpования кода мы вызываем SendMessage с хэндлом pодительского окна, WM_COMMAND, IDM_GETTEXT и 0. Это дает тот же эффект, что и выбоp пункта меню «Get Text». Пpоцедуpа окна не почувствует никакой pазницы.

Вы должны использовать эту технику так часто, насколько возможно, чтобы сделать ваш код более упоpядоченным.

И напоследок. Hе забудьте функцию TranslateMessage в очеpеди сообщений. Так как вам нужно печатать текст в edit box’е, ваша пpогpамма должна тpанслиpовать ввод в читабельный текст. Если вы пpопустите эту функцию, вы не сможете напечатать что-либо в вашем edit box’е. © Iczelion, пер. Aquila

Пустое окно на win api

Это довольно упрощенный пример для шага «1.26.2 Создание, перечисление и изменение размеров дочерних окон». Все максимально упрощено. За основу взят шаг «Шаг 4 — Окно Windows на С». Вот в него мы и добавляем изменения. Итак, смотрим код.

В момент обработки сообщения WM_CREATE мы создаем дочерние окна, для этого нужно сделать все естественно, зарегистрировать класс окна, вызвать функцию CreateWindow. Нужно создать функцию обработки сообщений ChildProc. Все мы это сделали. И как результат окна с дочерними окнами.

Если обратили внимание, я добавил разные описания курсоров:

Вы можете поводить мышкой и увидите, что курсор в дочернем окне изменяться.

Win32 API. Окна
Страница 12. Дочернее окно

Дочернее окно

Дочернее окно (child window) имеет стиль WS_CHILD и ограничено рабочей областью его родительского окна. Прикладная программа обычно использует дочерние окна, чтобы поделить рабочую область родительского окна на функциональные области. Вы создаете дочернее окно, определяя стиль WS_CHILD в функции CreateWindowEx.

Дочернее окно должно иметь родительское окно. Родительское окно может быть перекрывающим окном, выскакивающим окном или даже другим дочерним окном. Вы определяете родительское окно, когда Вы вызываете CreateWindowEx. Если Вы определяете стиль WS_CHILD в CreateWindowEx, но не определяете родительское окно, Windows не создает окно.

Дочернее окно имеет рабочую область, но никаких других функций, если они явно не затребованы. Прикладная программа может затребовать строку заголовка, меню окна, кнопки свертывания и развертывания окна, рамку и линейки прокрутки для дочернего окна, но дочернее окно не может иметь меню. Если прикладная программа определяет дескриптор меню, или когда она регистрирует класс дочернего окна, или когда создает дочернее окно, дескриптор меню игнорируется.

Позиционирование

Windows всегда устанавливает дочернее окно относительно верхнего левого угла рабочей области родительского окна. Никакая часть дочернего окна когда-либо не появляется снаружи рамок его родительского окна. Если прикладная программа создает дочернее окно, которое является большим чем родительское окно или устанавливает дочернее окно так, чтобы некоторые или все дочерние окна располагаются вне рамок родителя, Windows отсекает дочернее окно; то есть часть снаружи рабочей области родительского окна не отображается. Действия, которые воздействуют на родительское окно, могут также воздействовать на дочернее окно, следующим образом.

Закрепление

Windows автоматически не закрепляет дочернее окно с рабочей областью родительского окна. Это означает, что родительское окно делает прорисовку поверх дочернего окна, если оно выполняет какое-либо рисование, в том же самом месте, где дочернее окно. Однако, Windows скрепляет дочернее окно с рабочей областью родительского окна, если родительское окно имеет стиль WS_CLIPCHILDREN. Если дочернее окно закреплено, родительское окно не может рисовать поверх его.

Дочернее окно может накладываться на другие дочерние окна в той же самой рабочей области. Дочернее окно, которое разделяет то же самое родительское окно с одним или большим количеством других дочерних окон, называется сестринским окном (sibling window). Сестринские окна могут рисовать в рабочей области друг друга, если одно из дочерних окон не имеет стиля WS_CLIPSIBLINGS. Если дочернее окно имеет этот стиль, любая часть его сестринского окна, которое находится внутри дочернего окна, закрепляется.

Если окно имеет стиль WS_CLIPCHILDREN или WS_CLIPSIBLINGS, происходит небольшая потеря в эффективности. Каждое окно занимает системные ресурсы, так что прикладная программа не должна использовать дочерние окна беспорядочно. Для самой лучшей эффективности, прикладная программа, которой нужно логически поделить свое главное окно, должна сделать это в оконной процедуре главного окна скорее, чем используемые дочерние окна.

Взаимоотношение с родительским окном

Прикладная программа может изменять родительское окно существующего дочернего окна, вызывая функцию SetParent. В этом случае, Windows удаляет дочернее окно из рабочей области старого родительского окна и перемещает его в рабочую область нового родительского окна. Если SetParent определяет значение дескриптора ПУСТО (NULL), окно рабочего стола становится новым родительским окном. В этом случае, дочернее окно рисуется в самом главном окне, вне рамок любого другого окна. Функция GetParent восстанавливает дескриптор родительского окна для дочернего окна.

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

Дочернее окно имеет только одно родительское окно, но родитель может иметь любое число дочерних окон. Каждое дочернее окно, в свою очередь, может иметь дочерние окна. В этой цепочке окон, каждое дочернее окно называется порожденным окном первоначального родительского окна. Прикладная программа использует функцию IsChild, чтобы обнаружить, является ли данное окно дочерним окном или порожденным окном данного родительского окна.

Функция EnumChildWindows перечисляет дочерние окна родительского окна. Затем, EnumChildWindows передает дескриптор каждого дочернего окна в определенную прикладной программой функцию повторного вызова. Порожденные окна данного родительского окна также перечисляются.

Сообщения

Windows передает входящие сообщения дочернего окна непосредственно в дочернее окно; сообщения не передаются через родительское окно. Единственная исключительная ситуация является той, если дочернее окно было заблокировано функцией EnableWindow. В этом случае, Windows передает любые входные сообщения, которые пошли бы в дочернее окно в родительское окно. Это разрешает родительскому окну проверять входящие сообщения и, в случае необходимости, допускать их к дочернему окну.

Дочернее окно может иметь уникальный целочисленный идентификатор. Идентификаторы дочернего окна важны при работе с окнами элементов управления. Прикладная программа направляет действие элементов управления, посылая ему сообщения. Прикладная программа использует идентификаторы элементов управления дочернего окна, чтобы направлять сообщения в элемент управления. Кроме того, элемент управления посылает уведомительные сообщения своему родительскому окну. Уведомительное сообщение включает в себя идентификатор элемента управления дочернего окна, который родитель используют для определения, какому элементу управления послано сообщение. Прикладная программа определяет идентификатор дочернего окна для других типов дочерних окон, путем установки значения параметра hmenu функции CreateWindowEx скорее, чем дескриптор меню.

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL