FAQ:WinAPI, VCPP Part 4 — различия между версиями

Материал из Весельчак У
Перейти к: навигация, поиск
Строка 1: Строка 1:
===Как создавать всплывающие подсказки (ToolTip) ?===
+
===Как создавать всплывающие подсказки (ToolTip)?===
 
Этот элемент управления называется "Balloon ToolTip". (В МСДН есть статья под названием "Using ToolTip Controls")
 
Этот элемент управления называется "Balloon ToolTip". (В МСДН есть статья под названием "Using ToolTip Controls")
 
[[Изображение:context_help.GIF]]
 
[[Изображение:context_help.GIF]]
  
 
Тематические ссылки:
 
Тематические ссылки:
 +
* http://www.codeproject.com/shell/LiviuBirjegaCode.asp
 +
* http://www.codeproject.com/useritems/wtlntray.asp
  
http://www.codeproject.com/shell/LiviuBirjegaCode.asp
 
  
http://www.codeproject.com/useritems/wtlntray.asp
+
Для того, чтобы подсказка имела вид "облака" (как в комиксах), нужно установить недокументированный стиль
 
+
 
+
Для того, чтобы подсказка имела вид "облака" (как в коммиксах), нужно установить недокументированный стиль
+
 
TTS_BALLOON==0x40
 
TTS_BALLOON==0x40
  
 
Вот ещё пара полезных функций API для работы с подсказками
 
Вот ещё пара полезных функций API для работы с подсказками
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
CToolTipCtrl::SetDelayTime(TTDT_INITIAL, мс );//через какое время появится на экране после наведения курсора
+
CToolTipCtrl::SetDelayTime(TTDT_INITIAL, время_в_миллисекундах);//через какое время появится на экране после наведения курсора
CToolTipCtrl::SetDelayTime(TTDT_AUTOPOP, мс );//время горения подсказки на экране
+
CToolTipCtrl::SetDelayTime(TTDT_AUTOPOP, время_в_миллисекундах);//время горения подсказки на экране
  
//мс - время в миллисекундах , тип DWORD
+
//время в миллисекундах - тип DWORD
 
</syntaxhighlight>
 
</syntaxhighlight>
 
  
 
===Что делает функция ScrollWindow()===
 
===Что делает функция ScrollWindow()===
Строка 36: Строка 33:
 
===Как программно поменять настройки Internet Explorer?===
 
===Как программно поменять настройки Internet Explorer?===
 
Можно воспользоваться редактированием реестра:
 
Можно воспользоваться редактированием реестра:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\AdvancedOptions\ (всякие настройки)
 
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\AdvancedOptions\ (всякие настройки)
 
</syntaxhighlight>
 
</syntaxhighlight>
Строка 45: Строка 42:
 
===Как получить короткое и длинное имя файла?===
 
===Как получить короткое и длинное имя файла?===
 
Можно использовать функции API
 
Можно использовать функции API
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
GetShortPathName(
 
GetShortPathName(
 
LPCSTR lpszLongPath,
 
LPCSTR lpszLongPath,
Строка 52: Строка 49:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
и
 
и
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
GetLongPathName(
 
GetLongPathName(
 
LPCSTR lpszShortPath,
 
LPCSTR lpszShortPath,
Строка 61: Строка 58:
  
 
Например имеется путь к файлу:
 
Например имеется путь к файлу:
<syntaxhighlight>
+
 
D:\program files\Microsoft Office\OFFICE11\winword.exe
+
D:\program files\Microsoft Office\OFFICE11\winword.exe
</syntaxhighlight>
+
 
 
функция GetShortPathName() поможет привести его к виду:
 
функция GetShortPathName() поможет привести его к виду:
<syntaxhighlight>
+
 
d:\PROGRA~1\MICROS~2\OFFICE11\WINWORD.EXE
+
d:\PROGRA~1\MICROS~2\OFFICE11\WINWORD.EXE
</syntaxhighlight>
+
 
 
а функция GetLongPathName() - наоборот.
 
а функция GetLongPathName() - наоборот.
  
Строка 80: Строка 77:
 
=== Как из программы определить каталог, в котором находится эта программа?===
 
=== Как из программы определить каталог, в котором находится эта программа?===
 
Это можно сделать при помощи функции, которая возвращает абсолютное имя модуля.
 
Это можно сделать при помощи функции, которая возвращает абсолютное имя модуля.
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
GetModuleFileName()
 
GetModuleFileName()
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
В MFC можно использовать переменную-член класса CWinApp, определённую как
 
В MFC можно использовать переменную-член класса CWinApp, определённую как
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
LPCTSTR m_pszExeName;
 
LPCTSTR m_pszExeName;
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
Получить доступ можно двумя способами:
 
Получить доступ можно двумя способами:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
//1
 
//1
 
  AfxGetApp()->m_pszExeName;
 
  AfxGetApp()->m_pszExeName;
Строка 99: Строка 96:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
===Как получить полное имя пользователя и организации, то есть то, что на диалоге system properties (горячая кнопка [ Win ] + Break ) на закладке General перечисленно под пунктом Registred To? ===
+
===Как получить полное имя пользователя и организации, то есть то, что на диалоге system properties (горячая кнопка [ Win ] + Break ) на закладке General перечислено под пунктом Registred To? ===
 
Значение можно взять в реестре:
 
Значение можно взять в реестре:
  
 
тут (для  Windows NT)
 
тут (для  Windows NT)
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
 
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
или тут (W98, W95)
 
или тут (W98, W95)
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion
 
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion
 
</syntaxhighlight>
 
</syntaxhighlight>
  
===Как определить первый свободный ID, который можно использовать при динамичском создании элементов управления?===
+
===Как определить первый свободный ID, который можно использовать при динамическом создании элементов управления?===
 
Можно поступить так: начать перебор значений ID со значения 1000 и, проверяя функцией GetDlgItem(), увеличивать значение на единицу до тех пор, пока не будет найден свободный ID.
 
Можно поступить так: начать перебор значений ID со значения 1000 и, проверяя функцией GetDlgItem(), увеличивать значение на единицу до тех пор, пока не будет найден свободный ID.
  
 
===Как изменить цвет рамки приложения?===
 
===Как изменить цвет рамки приложения?===
Это можно сделать, если перехватить сообщение WM_NCPAINT, которое отвечает за прорисовку не-клиентской части окна.
+
Это можно сделать, если перехватить сообщение WM_NCPAINT, которое отвечает за прорисовку не клиентской части окна.
  
 
===Я запускаю экзешник при помощи ::ShellExecute(). Процедура тут же возвращает управление, а как дождаться, когда запущенный процесс завершится, только потом продолжить выполнение программы?===
 
===Я запускаю экзешник при помощи ::ShellExecute(). Процедура тут же возвращает управление, а как дождаться, когда запущенный процесс завершится, только потом продолжить выполнение программы?===
Строка 125: Строка 122:
 
WaitForSingeObject()
 
WaitForSingeObject()
  
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
STARTUPINFO StartupInfo;
+
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInfo;
+
PROCESS_INFORMATION ProcessInfo;
DWORD dwRetValue;
+
DWORD dwRetValue;
RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
+
RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof(StartupInfo);
+
StartupInfo.cb = sizeof(StartupInfo);
  
//запуск экзешника
+
//запуск экзешника
if(!CreateProcess(
+
if(!CreateProcess(
szApplicationName,
+
szApplicationName,
szCommandLine, //командная строка (можно указать NULL)
+
szCommandLine, //командная строка (можно указать NULL)
NULL, NULL, FALSE,
+
NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS,
+
NORMAL_PRIORITY_CLASS,
NULL,
+
NULL,
szCurrentDirectory, //рабочая директория (можно указать NULL)
+
szCurrentDirectory, //рабочая директория (можно указать NULL)
&StartupInfo,
+
&StartupInfo,
&ProcessInfo))
+
&ProcessInfo))
{
+
{
//ошибка запуска
+
//ошибка запуска
DWORD dwdErr=GetLastError(); //определяем ошибку
+
DWORD dwdErr=GetLastError(); //определяем ошибку
}
+
}
else
+
else
{
+
{
//ждём 30 секунд момента, пока процесс завершится
+
//ждём 30 секунд момента, пока процесс завершится
//(ProcessInfo.hProcess перейдёт в сигнальное состояние)
+
//(ProcessInfo.hProcess перейдёт в сигнальное состояние)
DWORD dwd=WaitForSingleObject(ProcessInfo.hProcess, 30000);
+
//если задать INFINITE, будет ждать до бесконечности
//если задать INFINITE , будет ждать до бесконечности
+
DWORD dwd=WaitForSingleObject(ProcessInfo.hProcess, 30000);
  
//dwd покажет причину завершения процедуры WaitForSingleObject
+
//dwd покажет причину завершения процедуры WaitForSingleObject
//WAIT_OBJECT_0 Состояние объекта переведено в сигнальное  
+
//WAIT_OBJECT_0 Состояние объекта переведено в сигнальное  
//WAIT_TIMEOUT Кончился таймаут
+
//WAIT_TIMEOUT Кончился таймаут
  
//к теме не относится, но для мутекса ещё есть возвращаемое значение:
+
//к теме не относится, но для мутекса ещё есть возвращаемое значение:
//WAIT_ABANDONED Объект является мутексом, который был занят потоком, затем поток завершился,
+
//WAIT_ABANDONED Объект является мутексом, который был занят потоком, затем поток завершился,
// не разблокировав мутекс. Мутекс находится в несигнальном состоянии
+
// не разблокировав мутекс. Мутекс находится в несигнальном состоянии
  
  
//если нужно - смотрим, какое значение вернуло приложение
+
//если нужно - смотрим, какое значение вернуло приложение
GetExitCodeProcess(ProcessInfo.hProcess, &dwRetValue);
+
GetExitCodeProcess(ProcessInfo.hProcess, &dwRetValue);
  
//освобождаем хендлы, открытые CreateProcess
+
//освобождаем хендлы, открытые CreateProcess
CloseHandle(ProcessInfo.hThread);
+
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
+
CloseHandle(ProcessInfo.hProcess);
}
+
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Строка 180: Строка 177:
  
 
Пример:
 
Пример:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
HICON m_hIcon;
+
HICON m_hIcon;
...
+
...
...
+
...
HICON m_hIcon = AfxGetApp()->LoadIcon(IDR_1);
+
HICON m_hIcon = AfxGetApp()->LoadIcon(IDR_1);
SetIcon(m_hIcon, TRUE);
+
SetIcon(m_hIcon, TRUE);
 
</syntaxhighlight>
 
</syntaxhighlight>
  

Версия 23:13, 23 октября 2008

Содержание

Как создавать всплывающие подсказки (ToolTip)?

Этот элемент управления называется "Balloon ToolTip". (В МСДН есть статья под названием "Using ToolTip Controls") Файл:Context help.GIF

Тематические ссылки:


Для того, чтобы подсказка имела вид "облака" (как в комиксах), нужно установить недокументированный стиль TTS_BALLOON==0x40

Вот ещё пара полезных функций API для работы с подсказками

CToolTipCtrl::SetDelayTime(TTDT_INITIAL, время_в_миллисекундах);//через какое время появится на экране после наведения курсора
CToolTipCtrl::SetDelayTime(TTDT_AUTOPOP, время_в_миллисекундах);//время горения подсказки на экране
 
//время в миллисекундах - тип DWORD

Что делает функция ScrollWindow()

Функция ScrollWindow() всего лишь двигает рисунок, уже нарисованный на контексте окна, на заданное количество пикселов.

К примеру, у имеется нарисованное изображение на клиентской части окна, и нужно сделать скролинг этой части.

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

Второй путь: Передвинуть ту часть, которая останется в зоне видимости, и дорисовать недостаюшую часть. Функция ScrollWindow() как раз и пригодится, чтобы передвинуть рисунок на заданное количество пикселов. Останется потом только дорисовать.

Почему список CComboBox не выпадает, хотя клавишами "вверх" и "вниз" значения перебираются?

Нужно задать высоту выпадающего списка: находясь в редакторе форм, нужно щёлкнуть по стрелке комбобокса и за нижний маркер растянуть вниз, тем самым и задать размер выпадающего списка.

Как программно поменять настройки Internet Explorer?

Можно воспользоваться редактированием реестра:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\AdvancedOptions\ (всякие настройки)

Как узнать, когда после запуска приложение уже готово к работе?

Можно переопределить функцию CWinApp::OnIdle. Эта функция вызывается всякий раз, когда в очереди сообщений приложения нет больше сообщений. Самый первый вызов функции будет соответствовать моменту, когда приложение стало быть готово к работе.

Как получить короткое и длинное имя файла?

Можно использовать функции API

GetShortPathName(
	LPCSTR lpszLongPath,
	LPSTR  lpszShortPath,
	DWORD    cchBuffer);	//получить короткий путь

и

GetLongPathName(
	LPCSTR lpszShortPath,
	LPSTR  lpszLongPath,
	DWORD    cchBuffer);	//получить полный путь


Например имеется путь к файлу:

D:\program files\Microsoft Office\OFFICE11\winword.exe

функция GetShortPathName() поможет привести его к виду:

d:\PROGRA~1\MICROS~2\OFFICE11\WINWORD.EXE

а функция GetLongPathName() - наоборот.

Максимальная длина пути файла равна MAX_PATH (==260) символам

В чём разница между сообщениями WM_MOVE и WM_MOVING?

Сообщение VM_MOVING посылается окну, когда пользователь перемещает окно.

Сообщение VM_MOVE посылается окну, когда пользователь завершил перемещение окна (отпустил кнопку мыши).

Как из программы определить каталог, в котором находится эта программа?

Это можно сделать при помощи функции, которая возвращает абсолютное имя модуля.

GetModuleFileName()

В MFC можно использовать переменную-член класса CWinApp, определённую как

LPCTSTR m_pszExeName;

Получить доступ можно двумя способами:

//1
 AfxGetApp()->m_pszExeName;
 
//2
//extern CMyApp theApp
theApp.m_pszExeName;

Как получить полное имя пользователя и организации, то есть то, что на диалоге system properties (горячая кнопка [ Win ] + Break ) на закладке General перечислено под пунктом Registred To?

Значение можно взять в реестре:

тут (для Windows NT)

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion

или тут (W98, W95)

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion

Как определить первый свободный ID, который можно использовать при динамическом создании элементов управления?

Можно поступить так: начать перебор значений ID со значения 1000 и, проверяя функцией GetDlgItem(), увеличивать значение на единицу до тех пор, пока не будет найден свободный ID.

Как изменить цвет рамки приложения?

Это можно сделать, если перехватить сообщение WM_NCPAINT, которое отвечает за прорисовку не клиентской части окна.

Я запускаю экзешник при помощи ::ShellExecute(). Процедура тут же возвращает управление, а как дождаться, когда запущенный процесс завершится, только потом продолжить выполнение программы?

Нужно использовать функции

CreateProcess()

WaitForSingeObject()

STARTUPINFO	StartupInfo;
PROCESS_INFORMATION ProcessInfo;
DWORD dwRetValue;
RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof(StartupInfo);
 
//запуск экзешника
if(!CreateProcess(
	szApplicationName,
	szCommandLine,		//командная строка (можно указать NULL)
	NULL, NULL, FALSE,
	NORMAL_PRIORITY_CLASS,
	NULL,
	szCurrentDirectory,	//рабочая директория (можно указать NULL)
	&StartupInfo,
	&ProcessInfo))
{
	//ошибка запуска
	DWORD dwdErr=GetLastError(); //определяем ошибку
}
else
{
	//ждём 30 секунд момента, пока процесс завершится
	//(ProcessInfo.hProcess перейдёт в сигнальное состояние)
	//если задать INFINITE, будет ждать до бесконечности
	DWORD dwd=WaitForSingleObject(ProcessInfo.hProcess, 30000);
 
	//dwd покажет причину завершения процедуры WaitForSingleObject
	//WAIT_OBJECT_0		Состояние объекта переведено в сигнальное 
	//WAIT_TIMEOUT		Кончился таймаут
 
	//к теме не относится, но для мутекса ещё есть возвращаемое значение:
	//WAIT_ABANDONED	Объект является мутексом, который был занят потоком, затем поток завершился,
	//					не разблокировав мутекс. Мутекс находится в несигнальном состоянии
 
 
	//если нужно - смотрим, какое значение вернуло приложение
	GetExitCodeProcess(ProcessInfo.hProcess, &dwRetValue);
 
	//освобождаем хендлы, открытые CreateProcess
	CloseHandle(ProcessInfo.hThread);
	CloseHandle(ProcessInfo.hProcess);
}

В szApplicationName может быть либо полный путь к файлу, либо только имя файла. В последнем случае файл будет искаться в текущем каталоге.

szCommandLine может быть NULL, если не надо передавать командную строку запускаемому процессу.

szCurrentDirectory может быть NULL, тогда текущий каталог будет как у родительского процесса.

Как сменить иконку у диалога или мейнфрейма? (поставить свою иконку из ресурсов)

Пример:

HICON m_hIcon;
...
...
HICON m_hIcon = AfxGetApp()->LoadIcon(IDR_1);
SetIcon(m_hIcon, TRUE);

где

IDR_1 - ИД иконки в ресурсах

m_hIcon - хендл типа HICON (естественно - не временный, а, скажем, член класса)