Сообщений 18    Оценка 4        Оценить  
Система Orphus

WinAPI Q&A

Авторы: Burd
Alex Fedotov
Alexey Goncharov
Andrew S

Источник: RSDN Magazine #5-2004
Опубликовано: 27.12.2002
Исправлено: 10.12.2016
Версия текста: 1.0
Q. Как реализовать функцию "свернуть все окна"?
Q. Объясните, пожалуйста, почему в книге Ч.Петзольда прототип диалоговой процедуры имеет вид:
Q. С помощью SetWindowRgn я скруглил углы моего диалога, но теперь нет возможности схватить за эти круглые края и изменить размер диалога. Как это сделать?
Q. Как запустить "My computer" и "Recycle Bin" из другого приложения? Заранее благодарен.

Q. Как реализовать функцию "свернуть все окна"?

A. Например, так:

HWND wnd = FindWindow("Shell_TrayWnd", NULL);

if (wnd != NULL)
    ::SendMessage(wnd, WM_COMMAND, 0x019f, 0); //Свернуть все окна

Q. Объясните, пожалуйста, почему в книге Ч.Петзольда прототип диалоговой процедуры имеет вид:

BOOL CALLBACK DlgProc(...)

а сейчас часто встречается:

INT_PTR WINAPI DlgProc(...)

Что это — макросы? При этом внутри диалоговой процедуры возвращается тип BOOL. INT_PTR – что-то для совместимости исходника с Win64, кажется, но что точно, и зачем я не понял.

A. И CALLBACK, и WINAPI устанавливают правильные соглашения о вызове (calling convention) для функции. Оба макроса раскрываются в __stdcall, так что принципиальной разницы между ними нет. Традиционно WINAPI используется с функциями "прямого вызова", такими, как функции Win32 API, а CALLBACK — с функциями "обратного вызова" (callback functions), например, оконные и диалоговые процедуры.

Повторюсь, функционально CALLBACK и WINAPI идентичны, но для повышения читабельности кода я бы использовал CALLBACK для диалоговых процедур.

Что касается типа возвращаемого значения, то изначально это был BOOL, так как предполагалось, что диалоговая процедура возвращает только TRUE или FALSE. Потом оказалось, что в ответ на ряд сообщений, таких, как WM_CTLCOLORxxx, диалоговая процедура возвращает хэндл кисти. Поскольку в Win32 API BOOL — это синоним int, который имеет такой же размер, как и хэндл, — 32 бита, то никаких проблем это не вызывало: достаточно было привести возвращаемое значение к BOOL.

Ситуация изменилась с переходом к Win64. В Win64 int по-прежнему имеет размер 32 бита, а хэндлы — 64 бита, как и указатели. Поэтому, если просто привести хэндл к BOOL, то старшие 32 бита будут безвозвратно потеряны. В результате, чтобы обеспечить переносимость к Win64, для возвращаемого значения диалоговой процедуры теперь используется тип INT_PTR. Название типа расшифровывается так – целое такого же размера, как и указатель, т.е. 32 бита на Win32 и 64 бита — на Win64.

Подводя итог, я лично писал бы:

INT_PTR CALLBACK DlgProc(...)

Q. С помощью SetWindowRgn я скруглил углы моего диалога, но теперь нет возможности схватить за эти круглые края и изменить размер диалога. Как это сделать?

A. Попробуйте обрабатывать WM_NCHITTEST (CWnd::OnNcHitTest), возвращая одну из констант, обозначающих край окна (HTBOTTOM, HTBOTTOMLEFT, HTBOTTOMRIGHT и так далее).

Q. Как запустить "My computer" и "Recycle Bin" из другого приложения? Заранее благодарен.

A. Использовать ShellExecuteEx, либо реализовать самому IShellBrowser, и через IShellFolder\IShellView создать новое окно.

Первый вариант проще:

SHELLEXECUTEINFO se;

SHGetSpecialFolderLocation(NULL,CSIDL_DRIVES, &lst);

ZeroMemory(&se, sizeof(se));
se.cbSize = sizeof(se);
se.fMask = SEE_MASK_IDLIST;
se.hwnd = NULL;
se.lpVerb = TEXT("open");
se.nShow = SW_SHOW;
se.lpIDList = lst;
ShellExecuteEx(&se);
CoTaskMemFree(lst);


Эта статья опубликована в журнале RSDN Magazine #5-2004. Информацию о журнале можно найти здесь
    Сообщений 18    Оценка 4        Оценить