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

Материал из Весельчак У
Перейти к: навигация, поиск
м (Удалил.)
(Создан редирект на FAQ:WinAPI_VCPP. Оптимизация для поисковых систем.)
 
(не показано 20 промежуточных версий 2 участников)
Строка 1: Строка 1:
 
+
#REDIRECT [[FAQ:WinAPI_VCPP]]
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
=== Как сделать обработчик сообщения для нескольких контролов сразу?  ===
+
 
+
Если без помощи визарда, то переопределить виртуальную OnCommand()
+
<pre>BOOL CMyDialog::OnCommand(WPARAM wParam, LPARAM lParam)
+
{
+
WORD wMess=(wParam&gt;&gt;16);//командное сообщение
+
int nID=(int)(wParam &amp;0x0000ffff));//ID контрола
+
HWND hW=(HWND)lParam;//хендл контрола
+
+
//смотрим, какой контрол
+
switch(nID)
+
{
+
//кнопки
+
case ID_BN1:
+
case ID_BN2:
+
case ID_BN3:
+
{
+
//смотрим, какое сообщение
+
switch(wMess)
+
{
+
case BN_CLICKED:{ ... }break;
+
}
+
}
+
break;
+
+
//едиты
+
case ID_ED1:
+
case ID_ED2:
+
case ID_ED3:
+
case ID_ED4:
+
{
+
//смотрим, какое сообщение
+
switch(wMess)
+
{
+
case EN_CHANGE:{ ... }break;
+
case EN_KILLFOCUS:{ ... }break;
+
}
+
}
+
break;
+
}
+
+
return CDialog::OnCommand(wParam, lParam);
+
}
+
</pre>
+
=== Когда запускаю программу, то все надписи на русском языке теряются - показываются вопросики. Что делать?  ===
+
 
+
Лечится так: непосредственно после создания проекта открываем дерево ресурсов и в свойствах каждого элемента дерева ставим язык Russian. Если этого не сделать сразу, то все русские буквы при компиляции ресурсов потеряются.
+
 
+
=== Как в проекте VC6 MFC получить путь, откуда запущен ЕХЕ?  ===
+
 
+
Использовать GetModuleFileName():
+
<pre> TCHAR pszFileName[MAX_PATH];
+
pszFileName[0]=0;
+
GetModuleFileName(NULL, pszFileName, MAX_PATH);
+
CString stModulePath =  pszFileName;
+
//ищем первый слеш с конца и удаляем
+
//его вместе с именем файла EXE
+
int nEnd = stModulePath.ReverseFind('\\');
+
stModulePath.Delete(nEnd, stModulePath.GetLength()-nEnd);
+
+
//stModulePath - содержит путь
+
</pre>
+
=== Как получить доступ к контролам на панели CReBar, принадлежащей классу MainFrame?  ===
+
<pre>#include "MainFrm.h"
+
+
//CMyApp - класс вашего приложения. theApp - глобальная переменная,
+
//поэтому для доступа к ней используем extern
+
extern CMyApp theApp;
+
 
+
void CMyView::F()
+
{
+
//Получаем главное окно приложения в любом месте программы
+
CMainFrame* pMainFrame=(CMainFrame*)(theApp.m_pMainWnd);
+
pMainFrame-&gt;m_wndDlgBar ....//Делаем что хотим
+
...
+
}
+
</pre>
+
=== Как загрузить и показать один из стандартных курсоров?  ===
+
<pre>HCURSOR hCursor;
+
hCursor=AfxGetApp()-&gt;LoadStandardCursor(IDC_UPARROW);
+
if(hCursor)SetCursor(hCursor);
+
</pre>
+
идентификаторы стандартных курсоров: IDC_ARROW IDC_IBEAM IDC_WAIT IDC_CROSS IDC_UPARROW IDC_SIZENWSE IDC_SIZENESW IDC_SIZEWE IDC_SIZENS IDC_SIZEALL
+
 
+
=== Как запретить пользователю закрыть программу нажатием на крестик?  ===
+
 
+
Нужно добавить обработчик сообщений WM_CLOSE - OnClose() - в главное окно программы. Для диалоговых приложений - это главный диалог, для одно- и много-документных - это CMainFrame.
+
<pre>void CMainFrame::OnClose()
+
{
+
if(......)
+
{
+
//не разрешаем закрыть
+
return;
+
}
+
+
CFrameWnd::OnClose();
+
}
+
</pre>
+
=== Как создать на диалоге группу RadioButton-ов и как задать порядок их обхода клавишей Tab?  ===
+
 
+
Кладём на форму N контролов RadioButton. Затем у первого из группы ставим свойство Group, у остальных в группе - убираем это свойство. Порядок обхода (Tab Order) задаётся так: нажимаем Ctrl+D (загораются номера таб-порядка). Затем щёлкаем элементы в группе в таком порядке, который требуется.
+
 
+
=== Где лучше устанавливать начальные значения CComboBox?  ===
+
 
+
1) В визарде (новая строка данных - Ctrl+Enter)
+
 
+
2) В функции OnInitDialog (для диалога) или OnInitialUpdate (для CView)
+
 
+
=== Как перевести RichEdit в режим замены символов?  ===
+
 
+
1) Программно, зная хендл контрола (hWnd):
+
 
+
::PostMessage(hWnd,WM_KEYDOWN,VK_INSERT,1);
+
 
+
2) Пользователь может нажать Insert.
+
 
+
=== Как вызвать метод класса CMainFrame (главное окно) из любого места программы?  ===
+
 
+
AfxGetApp()-&gt;m_pMainWnd-&gt; ...&nbsp;;
+
 
+
=== Как запретить появление полос прокруток на CFormView, когда пользователь делает размер главного окна меньше размера окна CFormView&nbsp;?  ===
+
 
+
методом SetScaleToFitSize():
+
<pre>void CMyView::OnInitialUpdate()
+
{
+
CFormView::OnInitialUpdate();
+
/////////
+
GetParentFrame()-&gt;RecalcLayout();
+
ResizeParentToFit();
+
SIZE s={0,0};
+
SetScaleToFitSize(s);
+
/////////
+
...
+
...
+
}
+
</pre>
+
=== Как нарисовать прямоугольник с вертикальным цветовым градиентом?  ===
+
 
+
pdc - указатель на контекст устройства pSize - указатель на структуру SIZE с размером прямоугольника dwdColor1, dwdColor2 - начальный и конечный цвет bySteps - количество шагов градиента (1...255)
+
<pre>//вертикальный градиент
+
void sFillVertGradientRect(CDC* pdc,SIZE *pSize, COLORREF dwdColor1, COLORREF dwdColor2,BYTE bySteps)
+
{
+
if(!bySteps)bySteps=1;
+
WORD i;
+
+
long W,H,x1,x2;
+
BYTE R1,G1,B1,R2,G2,B2;
+
float dh,dR,dG,dB,y1,y2,Rc,Gc,Bc;
+
+
//ширина и высота
+
W=pSize-&gt;cx;
+
H=pSize-&gt;cy;
+
+
//раскладываем цвета на их составляющие
+
R1=(BYTE)((dwdColor1&amp;0x000000ff));
+
G1=(BYTE)((dwdColor1&amp;0x0000ff00)&gt;&gt;8);
+
B1=(BYTE)((dwdColor1&amp;0x00ff0000)&gt;&gt;16);
+
R2=(BYTE)((dwdColor2&amp;0x000000ff));
+
G2=(BYTE)((dwdColor2&amp;0x0000ff00)&gt;&gt;8);
+
B2=(BYTE)((dwdColor2&amp;0x00ff0000)&gt;&gt;16);
+
+
//высота разноцветных прямоугольников
+
dh=((float)H)/((float)bySteps);
+
//величина шагов составляющих цветов
+
dR=(((float)R2)-((float)R1))/((float)bySteps);
+
dG=(((float)G2)-((float)G1))/((float)bySteps);
+
dB=(((float)B2)-((float)B1))/((float)bySteps);
+
//выводим прямоугольники
+
x1=0;x2=W;y1=0;y2=dh;
+
Rc=R1;Gc=G1;Bc=B1;
+
for(i=0;i&lt;bySteps;i++)
+
{
+
//текущий цвет
+
pdc-&gt;FillSolidRect(x1,(int)y1,x2-x1,(int)(y2-y1),RGB((BYTE)Rc,(BYTE)Gc,(BYTE)Bc));
+
//следующий цвет и координаты
+
y1+=dh;y2+=dh;
+
Rc+=dR;Gc+=dG;Bc+=dB;
+
}
+
}
+
</pre>
+
пример вызова:
+
<pre> SIZE Size={100,100};
+
sFillGradientRect(&amp;dc,&amp;Size, RGB(200,0,0), RGB(0,200,0),10);
+
</pre>
+
=== Как под Windows отслеживать изменение файла?  ===
+
 
+
Использовать функции:
+
 
+
  FindFirstChangeNotification
+
  FindNextChangeNotification
+
  FindCloseChangeNotification
+
 
+
=== Есть массив char[], как конвертировать его в CString?  ===
+
<pre> char buf[]="text";
+
+
//строка должна обязательно заканчиваться нулём.
+
+
//конвертируем так
+
CString txt(buf);
+
+
//или так
+
CString txt;
+
txt=buf;
+
</pre>
+
=== Как зарезервировать в CString буфер нужной длины?  ===
+
 
+
при помощи методов класса:  
+
 
+
  CString::GetBuffer
+
  и
+
  CString::GetBufferSetLength
+
 
+
Разница между CString::GetBuffer(nLen) и CString::GetBufferSetLength(nLen) в том, что первый возвращает строку не меньше заданной длины, а второй возвращает строку точно равную заданной длине. Обе могут перераспределять память если надо. В обычных случаях лучше GetBuffer.
+
 
+
Если содержимое буфера менялось, то после этого нужно вызвать CString::ReleaseBuffer с указанием новой длины. Значение -1 в вызове CString::ReleaseBuffer означает, что длина строки будет вычислена автоматом (функцией strlen) в методе."-1" удобно использовать, если известно, что строка заканчивается нулем.
+
 
+
=== Как передать больше одного параметр в процедуру потока?  ===
+
 
+
Определить структуру с указателями на всё любое, например:
+
<pre>struct mystr
+
{
+
CEdit* pEd;
+
CDialog* pDlg;
+
DWORD* pdwd;
+
int *pn;
+
};
+
</pre>
+
запуск потока:
+
<pre>mystr *pparam=new mystr;//экземпляр не должен быть временным!!!
+
memset(pparam,0,sizeof(*pparam));
+
pparam-&gt;pEd=...;
+
pparam-&gt;pdwd=...;
+
 
+
::AfxBeginThread(thread,pparam);
+
//тут экземпляр *(pparam) уже нельзя использовать!!!
+
//он удалиться в потоке
+
</pre>
+
в потоке:
+
<pre>//поток:
+
UINT threadLoader(LPVOID pParam)
+
{
+
mystr data=*((mystr*)pParam);
+
delete ((mystr*)pParam);//подчищаем память
+
 
+
...
+
data.pDlg-&gt;...;
+
(*data.pdwd)=...;
+
...
+
}
+
</pre>
+
=== Как убрать главное меню из CMainFrame?  ===
+
<pre>BOOL CMainFrame::PreCreateWindow(CREATESTRUCT&amp; cs)
+
{
+
//обнуляем хендл меню до вызова CFrameWnd::PreCreateWindow
+
cs.hMenu = 0;
+
+
if(&nbsp;!CFrameWnd::PreCreateWindow(cs) )
+
return FALSE;
+
...
+
...
+
}
+
</pre>
+
=== Как работающая программа может определить, что юзер завершает работу Windows?  ===
+
 
+
В этот момент всем процессам посылается сообщение WM_QUERYENDSESSION - его и нужно отловить в обработчике OnQueryEndSession(). Если вернуть из обработчика значение 0, то Windows продолжит работу.
+
 
+
=== Как сделать всплывающую подсказку для класса CWnd и классов, от него производных?  ===
+
 
+
Допустим, имеется диалог класса CMyDlg. Делаем подсказки для контролов. (для CStatic контролов не забудьте поставить свойство Notify)
+
<pre>class CMyDlg:puplic CDialog
+
{
+
CToolTipCtrl m_ToolTip;//мембер класса CMyDlg
+
//
+
};
+
+
//массив, в котором перечислены идентификаторы
+
//контролов и тексты подсказок к ним
+
struct{int ID;const char* pch;} m_a_Tips[]=
+
{
+
{IDC_BUTTON1,"КЫнопка"},
+
{IDC_STATIC1,"Текст"},
+
//
+
{0,0},//признак конца массива
+
};
+
+
//в инициализации диалога (хотя, в принципе,
+
//можно и не тут) создаём и привязываем подсказки
+
BOOL CMyDlg::OnInitDialog()
+
{
+
CDialog::OnInitDialog();
+
//
+
//создаём
+
m_ToolTip.Create(this);
+
//Привязка подсказок
+
for(int i=0; m_a_Tips[i].ID; i++)
+
{
+
m_ToolTip.AddTool(
+
GetDlgItem(m_a_Tips[i].ID),
+
m_a_Tips[i].pch);
+
}
+
+
//включаем показ подсказок
+
m_ToolTip.Activate(1);
+
...
+
...
+
}
+
+
//для того, чтобы подсказки отображались как реакция на движение
+
//курсора мыши, транслируем получаемые окнами сообщения в
+
//виртуальной PreTranslateMessage()
+
BOOL CMyDlg::PreTranslateMessage(MSG* pMsg)
+
{
+
//транслируем
+
if(m_ToolTip.m_hWnd)m_ToolTip.RelayEvent(pMsg);
+
+
...
+
...
+
return CDialog::PreTranslateMessage(pMsg);
+
}
+
</pre>
+
=== Как в отладчике VС просмотреть содержимое std::vector&lt;string&gt; V  ===
+
 
+
В режиме отладки открываем окно "Watch" (ALT+3) и вставляем выражения:
+
 
+
V._Myfirst - будет показан первый элемент V._Myfirst+1 - второй V._Myfirst+2 - и т.д.
+
 
+
=== Я вывожу на контекст устройства текст. Как определить в пикселах ширину и высоту выведенных символов текста?  ===
+
 
+
использовать процедуру API:
+
<pre>BOOL GetTextExtentPoint32(
+
HDC hdc,// хендл контекста
+
LPCTSTR lpString,// выводимая строка
+
int cbString,// длина строки в символах
+
LPSIZE lpSize// указатель на структуру SIZE, куда
+
//будут помещены размеры
+
);
+
</pre>
+
[[Category:FAQ]]
+

Текущая версия на 02:30, 9 ноября 2008

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