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

Материал из Весельчак У
Перейти к: навигация, поиск
(Перенаправление на FAQ:WinAPI VCPP)
 
(не показано 57 промежуточных версий 4 участников)
Строка 1: Строка 1:
===Имеется приложение на основе CRichEditView. Как узнать, что пользователь меняет текст?===
+
#REDIRECT [[FAQ:WinAPI_VCPP]]
Добавить обработчик сообщения EN_CHANGE. Сообщение генерируется CRichEditView каждый раз, когда пользователь изменяет текст в окне CRichEditView
+
===Чем метод CArray::GetSize отличается от метода CArray::GetCount?===
+
Абсолютно ничем. (Скорее всего, были предыдущие библиотеки, в которых функции, одинаковые по смыслу, имели разные имена. Поэтому в целях совместимости оставили оба)
+
===Как загрузить строку из ресурса?===
+
<pre>
+
CString m_Temp;
+
m_Temp.LoadString(ID_MYSTRING);
+
</pre>
+
===Как поменять иконку у элемента (item) в CListCtrl ?===
+
<pre>
+
//заполняем структуру LVITEM
+
LVITEM lvItem;
+
memset(&lvItem,0,sizeof(lvItem));
+
+
lvItem.mask = LVIF_IMAGE;//меняться будет картинка
+
lvItem.iItem = ...;// индекс элемента списка (Zero-based)
+
lvItem.iSubItem = 0;
+
lvItem.iImage = ...; //индекс иконки (из списка контрола)
+
+
pList->SetItem(& lvItem);
+
</pre>
+
===Имеется класс Class1, содержащий мембер типа указатель на Class2. В Class2 также имеется указатель на Class1. Компилятор выдаёт ошибку. Что надо делать?===
+
Предварительно объявляем класс Class2. Тогда компилятору будет известно, что описание класса Class2 будет встречено дальше, и станет возможным объявление указателей на класс до описания самого класса.
+
<pre>
+
Class2;//предопределение
+
+
Class1
+
{
+
Class2* p;
+
};
+
+
Class2
+
{
+
Class1* p;
+
};
+
</pre>
+
===Как переключить раскладку в другом (то есть в активном) процессе?===
+
Использовать функции:
+
  GetKeyboardLayout - определить текущую раскладку
+
  LoadKeyboardLayout - загрузить новую раскладку
+
 
+
см.также
+
  VerLanguageName - получить строку с описанием языка
+
 
+
(подробности - в MSDN)
+
===Как получить хендл контрола Edit зная его ID ?===
+
Пусть контрол лежит на окне CMyWnd
+
Тогда:
+
<pre>
+
void CMyWnd::некая_процедура()
+
{
+
//для MFC
+
CEdit* ed=(CEdit* ) GetDlgItem(ID_EDIT1);
+
HWND hwnd=ed->GetSafeHwnd();
+
...
+
+
//для Win32 API
+
HWND hwnd=GetDlgItem(m_hWnd,ID_EDIT1);
+
...
+
}
+
</pre>
+
===Как из дочернего окна закрыть приложение?===
+
Нужно послать родительскому окну (*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)
+
<pre>
+
//указатель на будущий буфер с BSTR.
+
// (По сути, BSTR определён как
+
// typedef WCHAR* BSTR;
+
// то есть указатель на 16-битный символ юникод)
+
+
BSTR bstrHE=0;
+
+
CString Str="мой текст";
+
+
//Выделить память и загрузить адрес блока в bstrHE
+
bstrHE=Str.AllocSysString();
+
+
//...
+
//тут работаем с bstrHE[]
+
//...
+
+
//освобождаем память
+
SysFreeString(bstrHE);
+
</pre>
+
===Как получить доступ к графическим ресурсам элементов текущей темы оформления 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() :
+
<pre>
+
void CPlayersPropsDialog::OnClose()
+
{
+
CDialog::OnClose();
+
CDialog::OnCancel();//добавлено
+
}
+
</pre>
+
===VC++6. Я написал простейший макрос, а компилятор на него ругается. ума не приложу, что за глюк?===
+
<pre>
+
#define my_macr(x,y,z) \
+
z=\
+
(x+y)*\
+
(x-y)
+
</pre>
+
Скорее всего после одного из символов соединения строк "\" имеется
+
пробел или табуляция. Их надо удалить. Можно найти их "наощупь", а
+
можно включить показ непечатных символов в студии. Найти эту команду
+
можно так:
+
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() :
+
<pre>
+
 
+
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;
+
}
+
</pre>
+
===Почему на моем компьютере экзешник, созданный в MFC запускается, а на других компьютерах - нет? Требует какую-то  dll-ку.===
+
Нужно выбирать режим Release :
+
 
+
Menu->Build->Configurations...->Release,
+
 
+
и экзешник, соответственно, брать из папки Release проекта
+
===Как в диалог добавить меню?===
+
Надо сделать в ресурсах меню, затем вставить в диалог:
+
 
+
открыть в редакторе диалог, в свойствах (во вкладке General, окошко Menu) указать идентивикатор ресурса меню.
+
При помощи визарда добавить для меню обработчики OnCommand() и OnUpdateСommand().
+
===Я добавил визардом меню в диалог. Добавил обработчики для пунктов меню. Но пункты работают, но OnUpdate для пунктов не вызывается - то есть не получается ни затенить, ни чек поставить. Что делать?===
+
В диалоге у меню апдейта не происходит сам, в отличие от мейнфрейма.
+
Для этого нужно сделать самим апдейт в обработчике сообщения WM_KICKIDLE.
+
Визардом обработчик не добавляется, поэтому можно переопределить
+
виртуальную DefWindowProc() и там обработать:
+
#include <afxpriv.h>  //этот файл надо включить, там определёна WM_KICKIDLE
+

Текущая версия на 19:43, 3 октября 2009

Перенаправление на: