FAQ:WinAPI, VCPP Part 4

Материал из Весельчак У
Перейти к: навигация, поиск

Содержание

Как создавать всплывающие подсказки (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::Run(). Эта функция вызывается непосредственно перед запуском оконной процедуры.
int CMyApp::Run() 
{
	// 1) приложение готово к работе, сейчас вызовется Run,
	//    в котором реализована обработка очереди сообщений процесса
 
	// 2) запускается очередь
	int res = /*return*/ CWinApp::Run();
 
	// 3) было получено сообщение WM_QUIT, вышли из CWinApp::Run()
 
	// 4) возвращаемое приложением значение
	return res;
}
  • Можно так же переопределить функцию 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 (естественно - не временный, а, скажем, член класса)