FAQ:WinAPI, VCPP Part 3

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

Содержание

Имеется приложение на основе CRichEditView. Как узнать, что пользователь меняет текст?

Добавить обработчик сообщения EN_CHANGE. Сообщение генерируется CRichEditView каждый раз, когда пользователь изменяет текст в окне CRichEditView

Чем метод CArray::GetSize отличается от метода CArray::GetCount?

Абсолютно ничем. (Скорее всего, были предыдущие библиотеки, в которых функции, одинаковые по смыслу, имели разные имена. Поэтому в целях совместимости оставили оба)

Как загрузить строку из ресурса?

CString m_Temp;
m_Temp.LoadString(ID_MYSTRING);

Как поменять иконку у элемента (item) в CListCtrl ?

//заполняем структуру LVITEM
LVITEM lvItem;
memset(&lvItem,0,sizeof(lvItem));
	
lvItem.mask = LVIF_IMAGE;//меняться будет картинка
lvItem.iItem = ...;// индекс элемента списка (Zero-based)
lvItem.iSubItem = 0;
lvItem.iImage = ...; //индекс иконки (из списка контрола)
	
pList->SetItem(& lvItem);

Имеется класс Class1, содержащий мембер типа указатель на Class2. В Class2 также имеется указатель на Class1. Компилятор выдаёт ошибку. Что надо делать?

Предварительно объявляем класс Class2. Тогда компилятору будет известно, что описание класса Class2 будет встречено дальше, и станет возможным объявление указателей на класс до описания самого класса.

Class2;//предопределение
	
Class1
{
	Class2* p;
};
	
Class2
{
	Class1* p;
};

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

Использовать функции:

  GetKeyboardLayout - определить текущую раскладку
  LoadKeyboardLayout - загрузить новую раскладку

см.также

  VerLanguageName - получить строку с описанием языка

(подробности - в MSDN)

Как получить хендл контрола Edit зная его ID ?

Пусть контрол лежит на окне CMyWnd Тогда:

void CMyWnd::некая_процедура()
{
	//для MFC
	CEdit* ed=(CEdit* ) GetDlgItem(ID_EDIT1);
	HWND hwnd=ed->GetSafeHwnd();
	...
	
	//для Win32 API
	HWND hwnd=GetDlgItem(m_hWnd,ID_EDIT1);
	...
}

Как из дочернего окна закрыть приложение?

Нужно послать родительскому окну (*pParent) сообщение WM_CLOSE:

pParent->PostMessage(WM_CLOSE);//MFC

или

::PostMessage(pParent->m_hWnd,WM_CLOSE,(WPARAM)0,(LPARAM)0);//API

Как корректно перевести BSTR в CString и наоборот?

1) Нужно просто присвоить переменной типа CString переменную типа BSTR. Оператор = класса CString сам всё переведёт.

2)

//указатель на будущий буфер с BSTR.
//	(По сути, BSTR определён как 
//	typedef WCHAR* BSTR;
//	то есть указатель на 16-битный символ юникод)
	
BSTR bstrHE=0;
	
CString Str="мой текст";
	
//Выделить память и загрузить адрес блока в bstrHE
bstrHE=Str.AllocSysString();
	
//...	
//тут работаем с bstrHE[]
//...
	
//освобождаем память
SysFreeString(bstrHE);

Как получить доступ к графическим ресурсам элементов текущей темы оформления Windows?

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

OpenThemeData() DrawThemeBackground() DrawFrameControl() CloseThemeData().

(подробности - в MSDN)

Имеется класс , производный от CDialog. Когда диалог в фокусе, нажатие на Enter или Esc приводит к закрытию диалога. Как это запретить?

При нажатии Enter происходит выполнение команды IDOK, при нажатии Esc - IDCANCEL. Нужно переопределить в классе виртуальные функции OnOk() и OnCancel(), которые соответственно вызываются для этих команд. При помощи визарда эти функции добавить можно так: Положить на диалог две кнопки с идентификаторами IDOK и IDCANCEL (при создании нового диалога они там есть сразу), затем двойной клик по кнопке добавляет соответствующий обработчик. В обработчиках надо удалить вызовы СDialog::OnOK() и CDialog::OnCancel(), тогда диалог закрываться не будет. Однако тогда диалог станет невозможно закрыть кнопкой с крестиком  :)

Лечить так: добавить обработчик сообщения WM_CLOSE - OnClose(), и в нём сделать вызов OnOk() или OnCancel() :

void CPlayersPropsDialog::OnClose() 
{
	CDialog::OnClose();
	CDialog::OnCancel();//добавлено
}

VC++6. Я написал простейший макрос, а компилятор на него ругается. ума не приложу, что за глюк?

	#define my_macr(x,y,z) \
		z=\
		(x+y)*\
		(x-y)

Скорее всего после одного из символов соединения строк "\" имеется пробел или табуляция. Их надо удалить. Можно найти их "наощупь", а можно включить показ непечатных символов в студии. Найти эту команду можно так: Tools->Customize...->вкладка Commands. , В окошке Category выбрать "Edit", и среди кнопок справа найти кнопку , на которой написано "a.b" Эту кнопку надо перетащить на одну из панелей инструментов студии.

Как получить список всех процесов, включая idle ?

Использовать функции Process32First() Precess32Next()

Как программно установить переменные окружения?

Чтобы добавить или изменить их программно, необходимо воспользоваться ключом реестра HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\ Session Manager\Environment, а затем отправить широковещательное сообщение WM_SETTINGCHANGE. Это позволит приложениям узнать об изменениях:

SendMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0);

Как сделать,чтобы у окна был черный фон?

переопределить обработчик сообщения WM_CTLCOLOR - OnCtlColor() :


CBrush br(RGB(0,0,0));
	
HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
	HBRUSH hbr = CMyDlg::OnCtlColor(pDC, pWnd, nCtlColor);
	
	//фон диалога (или вьюшки)
	if(nCtlColor==CTLCOLOR_DLG)
	{
		return (HBRUSH)br;
	}
	
	//фон статиков (если нужно)
	if(nCtlColor==CTLCOLOR_STATIC)
	{
		//делаем фон текста статика прозрачным
		pDC->SetBkMode(TRANSPARENT);
		return (HBRUSH)br;
	}
	
	return hbr;
}

Почему на моем компьютере экзешник, созданный в MFC запускается, а на других компьютерах - нет? Требует какую-то dll-ку.

Нужно выбирать режим Release :

Menu->Build->Configurations...->Release,

и экзешник, соответственно, брать из папки Release проекта

Как в диалог добавить меню?

Надо сделать в ресурсах меню, затем вставить в диалог:

открыть в редакторе диалог, в свойствах (во вкладке General, окошко Menu) указать идентивикатор ресурса меню. При помощи визарда добавить для меню обработчики OnCommand() и OnUpdateСommand().

Я добавил визардом меню в диалог. Добавил обработчики для пунктов меню. Но пункты работают, но OnUpdate для пунктов не вызывается - то есть не получается ни затенить, ни чек поставить. Что делать?

В диалоге у меню апдейта не происходит сам, в отличие от мейнфрейма. Для этого нужно сделать самим апдейт в обработчике сообщения WM_KICKIDLE. Визардом обработчик не добавляется, поэтому можно переопределить виртуальную DefWindowProc() и там обработать:

#include <afxpriv.h>   //этот файл надо включить, там определёна WM_KICKIDLE