FAQ:WinAPI, VCPP Part 2 — различия между версиями
RXL (обсуждение | вклад) м (→Как запретить появление полос прокруток на форме класса CFormView, когда пользователь делает размер главного окна меньше размера формы ?) |
|||
Строка 1: | Строка 1: | ||
− | ===Как сделать обработчик сообщения для нескольких | + | ===Как сделать обработчик сообщения для нескольких элементов управления сразу?=== |
Без помощи визарда (Wizard) это можно сделать переопределением виртуальной функции OnCommand(): | Без помощи визарда (Wizard) это можно сделать переопределением виртуальной функции OnCommand(): | ||
Строка 6: | Строка 6: | ||
BOOL CMyDialog::OnCommand(WPARAM wParam, LPARAM lParam) | BOOL CMyDialog::OnCommand(WPARAM wParam, LPARAM lParam) | ||
{ | { | ||
− | WORD wMess = (wParam >> 16); // | + | //командное сообщение |
− | int nID = (int)(wParam &0x0000ffff)); // | + | WORD wMess=(wParam >> 16); |
− | HWND hW = (HWND)lParam; | + | |
+ | //ID элемента управления | ||
+ | int nID=(int)(wParam &0x0000ffff)); | ||
+ | |||
+ | //хендл элемента управления | ||
+ | HWND hW=(HWND)lParam; | ||
− | // смотрим, какой | + | // смотрим, какой элемент управления |
switch (nID) | switch (nID) | ||
{ | { | ||
− | //кнопки | + | //CButton (кнопки, переключатели, флажки) |
case ID_BN1: | case ID_BN1: | ||
case ID_BN2: | case ID_BN2: | ||
Строка 21: | Строка 26: | ||
switch (wMess) | switch (wMess) | ||
{ | { | ||
− | case BN_CLICKED: { ... } break; | + | case BN_CLICKED: |
+ | { | ||
+ | ... | ||
+ | } | ||
+ | break; | ||
} | } | ||
} | } | ||
break; | break; | ||
− | + | //CEdit | |
case ID_ED1: | case ID_ED1: | ||
case ID_ED2: | case ID_ED2: | ||
Строка 35: | Строка 44: | ||
switch (wMess) | switch (wMess) | ||
{ | { | ||
− | case EN_CHANGE: { ... } break; | + | case EN_CHANGE: |
− | case EN_KILLFOCUS: { ... } break; | + | { |
+ | ... | ||
+ | } | ||
+ | break; | ||
+ | |||
+ | case EN_KILLFOCUS: | ||
+ | { | ||
+ | ... | ||
+ | } | ||
+ | break; | ||
} | } | ||
} | } | ||
Строка 54: | Строка 72: | ||
Нужно использовать функцию GetModuleFileName(): | Нужно использовать функцию GetModuleFileName(): | ||
− | <syntaxhighlight> | + | <syntaxhighlight lang="cpp"> |
TCHAR pszFileName[MAX_PATH]; | TCHAR pszFileName[MAX_PATH]; | ||
− | pszFileName[0] = 0; | + | pszFileName[0]=0; |
GetModuleFileName(NULL, pszFileName, MAX_PATH); | GetModuleFileName(NULL, pszFileName, MAX_PATH); | ||
− | CString stModulePath = pszFileName; | + | CString stModulePath=pszFileName; |
// ищем первый слеш с конца и удаляем | // ищем первый слеш с конца и удаляем | ||
// его вместе с именем файла EXE | // его вместе с именем файла EXE | ||
− | int nEnd = stModulePath.ReverseFind('\\'); | + | int nEnd=stModulePath.ReverseFind('\\');//' |
stModulePath.Delete(nEnd, stModulePath.GetLength() - nEnd); | stModulePath.Delete(nEnd, stModulePath.GetLength() - nEnd); | ||
Строка 82: | Строка 100: | ||
{ | { | ||
// Получаем главное окно приложения в любом месте программы | // Получаем главное окно приложения в любом месте программы | ||
− | CMainFrame* pMainFrame = (CMainFrame*)(theApp.m_pMainWnd); | + | CMainFrame* pMainFrame=(CMainFrame*)(theApp.m_pMainWnd); |
− | pMainFrame->m_wndDlgBar ....; // Делаем что хотим | + | pMainFrame->m_wndDlgBar. ...; // Делаем что хотим |
... | ... | ||
} | } | ||
Строка 94: | Строка 112: | ||
HCURSOR hCursor; | HCURSOR hCursor; | ||
− | hCursor = AfxGetApp()->LoadStandardCursor(IDC_UPARROW); | + | hCursor=AfxGetApp()->LoadStandardCursor(IDC_UPARROW); |
− | if (hCursor) | + | if(hCursor) |
+ | { | ||
SetCursor(hCursor); | SetCursor(hCursor); | ||
+ | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Строка 114: | Строка 134: | ||
===Как запретить пользователю закрыть программу нажатием на кнопку с крестиком?=== | ===Как запретить пользователю закрыть программу нажатием на кнопку с крестиком?=== | ||
− | Для этого нужно добавить обработчик сообщения WM_CLOSE (функция OnClose() в MFC) в главное окно программы. Для диалоговых приложений такое окно - это главный диалог, для одно- и | + | Для этого нужно добавить обработчик сообщения WM_CLOSE (функция OnClose() в MFC) в главное окно программы. Для диалоговых приложений такое окно - это главный диалог, для одно- и многодокументных приложений - это CMainFrame. |
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
void CMainFrame::OnClose() | void CMainFrame::OnClose() | ||
{ | { | ||
− | if ( | + | if(...) |
{ | { | ||
// не разрешаем закрыть | // не разрешаем закрыть | ||
Строка 149: | Строка 169: | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | // помещаем | + | // помещаем сообщение WM_KEYDOWN с нужными параметрами |
− | + | //в конец очереди сообщений элемента управления | |
::PostMessage(hWnd, WM_KEYDOWN, VK_INSERT, 1); | ::PostMessage(hWnd, WM_KEYDOWN, VK_INSERT, 1); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Строка 161: | Строка 181: | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | AfxGetApp()->m_pMainWnd-> ...; | + | AfxGetApp()->m_pMainWnd->...; |
</syntaxhighlight> | </syntaxhighlight> | ||
Строка 167: | Строка 187: | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
extern CMyAppXXX theApp; // здесь CMyAppXXX - название класса вашего приложения | extern CMyAppXXX theApp; // здесь CMyAppXXX - название класса вашего приложения | ||
− | theApp.m_pMainWnd-> ...; | + | theApp.m_pMainWnd->...; |
</syntaxhighlight> | </syntaxhighlight> | ||
− | ===Как запретить появление полос прокруток на форме класса CFormView, когда пользователь делает размер главного окна меньше размера формы ?=== | + | ===Как запретить появление полос прокруток на форме класса CFormView, когда пользователь делает размер главного окна меньше размера формы?=== |
Это можно сделать методом SetScaleToFitSize(): | Это можно сделать методом SetScaleToFitSize(): | ||
Строка 181: | Строка 201: | ||
// скрываем полосы прокрутки | // скрываем полосы прокрутки | ||
GetParentFrame()->RecalcLayout(); | GetParentFrame()->RecalcLayout(); | ||
− | + | ||
− | SIZE s = {0, 0}; | + | // это уберёт полосы прокрутки со вьюхи |
+ | ResizeParentToFit(); | ||
+ | |||
+ | SIZE s={0, 0}; | ||
SetScaleToFitSize(s); | SetScaleToFitSize(s); | ||
// далее вызовется обработчик OnPaint(), о котором ниже | // далее вызовется обработчик OnPaint(), о котором ниже | ||
− | // ... | + | //... |
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Также обратите внимание на одну особенность: в отладочной версии программы вызов OnPaint после выполнения SetScaleToFitSize() с параметром s = {0, 0} происходит с ошибкой (программа при этом завершается). | + | Также обратите внимание на одну особенность: в отладочной версии программы вызов OnPaint после выполнения SetScaleToFitSize() с параметром s={0, 0} происходит с ошибкой (программа при этом завершается). |
Обходится это так: | Обходится это так: | ||
Строка 215: | Строка 238: | ||
===Как нарисовать прямоугольник с вертикальным цветовым градиентом?=== | ===Как нарисовать прямоугольник с вертикальным цветовым градиентом?=== | ||
− | Нужно | + | Нужно задать граничные значения цветов, затем равномерно нарисовать несколько прямоугольников постепенно меняющегося цвета. Количество прямоугольников, а, значит - плавность градиента, задаётся точностью. |
Пример: | Пример: | ||
Строка 229: | Строка 252: | ||
COLORREF dwdColor2, BYTE bySteps) | COLORREF dwdColor2, BYTE bySteps) | ||
{ | { | ||
− | WORD i; | + | WORD i=0; |
− | long W | + | long W=0; |
− | BYTE R1 | + | long H=0; |
− | float dh | + | long x1=0; |
+ | long x2=0; | ||
+ | |||
+ | BYTE R1=0; | ||
+ | BYTE G1=0; | ||
+ | BYTE B1=0; | ||
+ | BYTE R2=0; | ||
+ | BYTE G2=0; | ||
+ | BYTE B2=0; | ||
+ | |||
+ | float dh=0; | ||
+ | float dR=0; | ||
+ | float dG=0; | ||
+ | float dB=0; | ||
+ | float y1=0; | ||
+ | float y2=0; | ||
+ | float Rc=0; | ||
+ | float Gc=0; | ||
+ | float Bc=0; | ||
− | if (!bySteps) | + | if(!bySteps) |
− | bySteps = 1; | + | { |
+ | bySteps=1; | ||
+ | } | ||
//ширина и высота | //ширина и высота | ||
− | W = pSize->cx; | + | W=pSize->cx; |
− | H = pSize->cy; | + | H=pSize->cy; |
// раскладываем цвета на их составляющие | // раскладываем цвета на их составляющие | ||
// для удобства дальнейших вычислений | // для удобства дальнейших вычислений | ||
− | R1 = (BYTE)((dwdColor1 & 0x000000ff)); | + | R1=(BYTE)((dwdColor1 & 0x000000ff) ); |
− | G1 = (BYTE)((dwdColor1 & 0x0000ff00) >> 8); | + | G1=(BYTE)((dwdColor1 & 0x0000ff00) >> 8 ); |
− | B1 = (BYTE)((dwdColor1 & 0x00ff0000) >> 16); | + | B1=(BYTE)((dwdColor1 & 0x00ff0000) >> 16 ); |
− | R2 = (BYTE)((dwdColor2 & 0x000000ff)); | + | R2=(BYTE)((dwdColor2 & 0x000000ff) ); |
− | G2 = (BYTE)((dwdColor2 & 0x0000ff00) >> 8); | + | G2=(BYTE)((dwdColor2 & 0x0000ff00) >> 8 ); |
− | B2 = (BYTE)((dwdColor2 & 0x00ff0000) >> 16); | + | B2=(BYTE)((dwdColor2 & 0x00ff0000) >> 16 ); |
// высота разноцветных прямоугольников | // высота разноцветных прямоугольников | ||
− | dh = | + | dh=(float)H / (float)bySteps; |
// величина шагов составляющих цветов | // величина шагов составляющих цветов | ||
− | dR = | + | dR=(float)(R2 - R1) / (float)bySteps; |
− | dG = | + | dG=(float)(G2 - G1) / (float)bySteps; |
− | dB = | + | dB=(float)(B2 - B1) / (float)bySteps; |
// выводим прямоугольники | // выводим прямоугольники | ||
− | x1 = 0; | + | x1=0; |
− | x2 = W; | + | x2=W; |
− | y1 = 0; | + | y1=0; |
− | y2 = dh; | + | y2=dh; |
− | Rc = R1; | + | Rc=R1; |
− | Gc = G1; | + | Gc=G1; |
− | Bc = B1; | + | Bc=B1; |
− | for (i = 0; i < bySteps; i++) | + | for(i=0; i<bySteps; i++) |
{ | { | ||
// текущий цвет | // текущий цвет | ||
pdc->FillSolidRect( | pdc->FillSolidRect( | ||
x1, | x1, | ||
− | (int)y1, x2 - x1, | + | (int)y1, |
− | (int)(y2 - y1), | + | x2-x1, |
− | RGB((BYTE)Rc, | + | (int)(y2-y1), |
− | + | RGB((BYTE)Rc, (BYTE)Gc, (BYTE)Bc) | |
− | + | ||
); | ); | ||
// следующий цвет и координаты | // следующий цвет и координаты | ||
− | y1 += dh; | + | y1+=dh; |
− | y2 += dh; | + | y2+=dh; |
− | Rc += dR; | + | Rc+=dR; |
− | Gc += dG; | + | Gc+=dG; |
− | Bc += dB; | + | Bc+=dB; |
} | } | ||
} | } | ||
Строка 292: | Строка 334: | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | SIZE Size = {100, 100}; | + | SIZE Size={100, 100}; |
− | sFillGradientRect(&dc, &Size, RGB(200, 0, 0), RGB(0, 200, 0), 10); | + | sFillGradientRect(&dc, &Size, RGB(200,0,0), RGB(0,200,0), 10); |
</syntaxhighlight> | </syntaxhighlight> | ||
Строка 310: | Строка 352: | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | char buf[] = "text"; | + | char buf[]="text"; |
// строка должна обязательно заканчиваться нулём!!! | // строка должна обязательно заканчиваться нулём!!! | ||
Строка 318: | Строка 360: | ||
// или так | // или так | ||
CString txt; | CString txt; | ||
− | txt = buf; | + | txt=buf; |
</syntaxhighlight> | </syntaxhighlight> | ||
Строка 358: | Строка 400: | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | mystr *pparam = new mystr; // экземпляр не должен быть временным!!! | + | mystr *pparam=new mystr; // экземпляр не должен быть временным!!! |
memset(pparam, 0, sizeof(*pparam)); | memset(pparam, 0, sizeof(*pparam)); | ||
− | pparam->pEd = ...; | + | pparam->pEd=...; |
− | pparam->pdwd = ...; | + | pparam->pdwd=...; |
::AfxBeginThread(thread, pparam); | ::AfxBeginThread(thread, pparam); | ||
// тут экземпляр *(pparam) уже нельзя использовать в нашем примере, так как | // тут экземпляр *(pparam) уже нельзя использовать в нашем примере, так как | ||
− | // он у нас | + | // он у нас удалился в процедуре потока |
</syntaxhighlight> | </syntaxhighlight> | ||
Строка 376: | Строка 418: | ||
{ | { | ||
// копируем данные из структуры в локальную структуру | // копируем данные из структуры в локальную структуру | ||
− | mystr data = *((mystr*)pParam); | + | mystr data=*((mystr*)pParam); |
// освобождаем память временной структуры | // освобождаем память временной структуры | ||
delete ((mystr*)pParam); | delete ((mystr*)pParam); | ||
− | pParam = 0; | + | pParam=0; |
... | ... | ||
data.pDlg->...; | data.pDlg->...; | ||
− | (*data.pdwd) = ...; | + | (*data.pdwd)=...; |
... | ... | ||
} | } | ||
Строка 396: | Строка 438: | ||
{ | { | ||
// обнуляем хендл меню до вызова CFrameWnd::PreCreateWindow | // обнуляем хендл меню до вызова CFrameWnd::PreCreateWindow | ||
− | cs.hMenu = 0; | + | cs.hMenu=0; |
− | if (!CFrameWnd::PreCreateWindow(cs)) | + | if(!CFrameWnd::PreCreateWindow(cs)) |
+ | { | ||
return FALSE; | return FALSE; | ||
+ | } | ||
... | ... | ||
Строка 411: | Строка 455: | ||
===Как сделать всплывающую подсказку для класса CWnd и классов, от него производных?=== | ===Как сделать всплывающую подсказку для класса CWnd и классов, от него производных?=== | ||
− | Допустим, имеется диалог класса CMyDlg. Делаем подсказки для элементов управления (для CStatic | + | Допустим, имеется диалог класса CMyDlg. Делаем подсказки для элементов управления (для элементов управления CStatic не забудьте поставить свойство Notify): |
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
Строка 419: | Строка 463: | ||
}; | }; | ||
− | // массив, в котором перечислены идентификаторы | + | // массив, в котором перечислены идентификаторы элементов управления |
− | // | + | // и тексты подсказок к ним |
struct | struct | ||
{ | { | ||
int ID; | int ID; | ||
const char* pch; | const char* pch; | ||
− | } | + | }; |
− | m_a_Tips[] = | + | |
+ | m_a_Tips[]= | ||
{ | { | ||
{IDC_BUTTON1, "Кнопка"}, | {IDC_BUTTON1, "Кнопка"}, | ||
Строка 443: | Строка 488: | ||
// Привязка подсказок | // Привязка подсказок | ||
− | for (int i = 0; m_a_Tips[i].ID; i++) | + | for(int i=0; m_a_Tips[i].ID; i++) |
{ | { | ||
m_ToolTip.AddTool( | m_ToolTip.AddTool( | ||
Строка 463: | Строка 508: | ||
{ | { | ||
// транслируем | // транслируем | ||
− | if (m_ToolTip.m_hWnd) | + | if(m_ToolTip.m_hWnd) |
+ | { | ||
m_ToolTip.RelayEvent(pMsg); | m_ToolTip.RelayEvent(pMsg); | ||
+ | } | ||
return CDialog::PreTranslateMessage(pMsg); | return CDialog::PreTranslateMessage(pMsg); | ||
Строка 481: | Строка 528: | ||
* "V._Myfirst" - будет показан первый элемент V | * "V._Myfirst" - будет показан первый элемент V | ||
* "V._Myfirst+1" - второй элемент V | * "V._Myfirst+1" - второй элемент V | ||
− | и | + | * и так далее |
===Как при выводе текста на контекст устройства определить ширину и высоту выведенных символов текста в пикселах?=== | ===Как при выводе текста на контекст устройства определить ширину и высоту выведенных символов текста в пикселах?=== |
Версия 22:01, 23 октября 2008
Содержание
- 1 Как сделать обработчик сообщения для нескольких элементов управления сразу?
- 2 Когда я запускаю программу, все надписи на русском языке теряются - показываются вопросики. Что делать?
- 3 Как в проекте VC6 MFC программно получить путь, откуда был запущен экзешник (исполняемый модуль) самой программы?
- 4 Как получить доступ к элементам управления панели CReBar, принадлежащей классу MainFrame?
- 5 Как загрузить и показать один из стандартных курсоров?
- 6 Как запретить пользователю закрыть программу нажатием на кнопку с крестиком?
- 7 Как создать на диалоге группу элементов "RadioButton" и как задать порядок их обхода клавишей Tab?
- 8 Где лучше устанавливать начальные значения элемента CComboBox?
- 9 Как перевести RichEdit в режим замены символов?
- 10 Как вызвать метод главного окна (если используется класс CMainFrame) из любого места программы?
- 11 Как запретить появление полос прокруток на форме класса CFormView, когда пользователь делает размер главного окна меньше размера формы?
- 12 Как нарисовать прямоугольник с вертикальным цветовым градиентом?
- 13 Как под Windows отслеживать изменение файла?
- 14 Как конвертировать массив char[] в CString?
- 15 Как зарезервировать в CString буфер нужной длины?
- 16 Как передать больше одного параметр в процедуру потока?
- 17 Как убрать главное меню из окна CMainFrame?
- 18 Как работающая программа может определить, что пользователь завершает работу Windows?
- 19 Как сделать всплывающую подсказку для класса CWnd и классов, от него производных?
- 20 Как в отладчике Visual С++ просмотреть содержимое std::vector<string>?
- 21 Как при выводе текста на контекст устройства определить ширину и высоту выведенных символов текста в пикселах?
Как сделать обработчик сообщения для нескольких элементов управления сразу?
Без помощи визарда (Wizard) это можно сделать переопределением виртуальной функции OnCommand():
BOOL CMyDialog::OnCommand(WPARAM wParam, LPARAM lParam) { //командное сообщение WORD wMess=(wParam >> 16); //ID элемента управления int nID=(int)(wParam &0x0000ffff)); //хендл элемента управления HWND hW=(HWND)lParam; // смотрим, какой элемент управления switch (nID) { //CButton (кнопки, переключатели, флажки) case ID_BN1: case ID_BN2: case ID_BN3: { //смотрим, какое сообщение switch (wMess) { case BN_CLICKED: { ... } break; } } break; //CEdit 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); }
Когда я запускаю программу, все надписи на русском языке теряются - показываются вопросики. Что делать?
Лечится проблема так: непосредственно после создания проекта открываем дерево ресурсов и в свойствах каждого элемента дерева ставим язык Russian. Если этого не сделать сразу, то все русские буквы при компиляции ресурсов потеряются.
Как в проекте VC6 MFC программно получить путь, откуда был запущен экзешник (исполняемый модуль) самой программы?
Нужно использовать функцию GetModuleFileName():
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 - содержит путь
Как получить доступ к элементам управления панели CReBar, принадлежащей классу MainFrame?
#include "MainFrm.h" // CMyApp - класс вашего приложения. theApp - глобальная переменная, // поэтому для доступа к ней используем extern extern CMyApp theApp; void CMyView::F() { // Получаем главное окно приложения в любом месте программы CMainFrame* pMainFrame=(CMainFrame*)(theApp.m_pMainWnd); pMainFrame->m_wndDlgBar. ...; // Делаем что хотим ... }
Как загрузить и показать один из стандартных курсоров?
HCURSOR hCursor; hCursor=AfxGetApp()->LoadStandardCursor(IDC_UPARROW); if(hCursor) { SetCursor(hCursor); }
Идентификаторы стандартных курсоров:
- IDC_ARROW
- IDC_IBEAM
- IDC_WAIT
- IDC_CROSS
- IDC_UPARROW
- IDC_SIZENWSE
- IDC_SIZENESW
- IDC_SIZEWE
- IDC_SIZENS
- IDC_SIZEALL
Как запретить пользователю закрыть программу нажатием на кнопку с крестиком?
Для этого нужно добавить обработчик сообщения WM_CLOSE (функция OnClose() в MFC) в главное окно программы. Для диалоговых приложений такое окно - это главный диалог, для одно- и многодокументных приложений - это CMainFrame.
void CMainFrame::OnClose() { if(...) { // не разрешаем закрыть return; } CFrameWnd::OnClose(); }
Как создать на диалоге группу элементов "RadioButton" и как задать порядок их обхода клавишей Tab?
Последовательность действий следующая:
- Помещаем на форму нужное количество элементов RadioButton;
- У первого элемента из группы ставим свойство Group, у остальных в группе - убираем это свойство;
- Порядок обхода (Tab Order) задаётся так: нажимаем Ctrl+D (загораются номера таб-порядка). Затем щёлкаем элементы в группе в таком порядке, который требуется.
Где лучше устанавливать начальные значения элемента CComboBox?
Это можно сделать парой способов:
- В редакторе форм - открыть свойства элемента CComboBox, "данные" (для ввода очередной строки данныхых нажать Ctrl+Enter);
- В функции OnInitDialog (в случае диалога) или в функции OnInitialUpdate (для CView).
Как перевести RichEdit в режим замены символов?
Имеется несколько способов.
1. Программно, если известен хендл элемента (hWnd), это делается так:
// помещаем сообщение WM_KEYDOWN с нужными параметрами //в конец очереди сообщений элемента управления ::PostMessage(hWnd, WM_KEYDOWN, VK_INSERT, 1);
2. Пользователь во время работы может нажать клавишу Insert.
Как вызвать метод главного окна (если используется класс CMainFrame) из любого места программы?
Это можно сделать так:
AfxGetApp()->m_pMainWnd->...;
или так
extern CMyAppXXX theApp; // здесь CMyAppXXX - название класса вашего приложения theApp.m_pMainWnd->...;
Как запретить появление полос прокруток на форме класса CFormView, когда пользователь делает размер главного окна меньше размера формы?
Это можно сделать методом SetScaleToFitSize():
void CMyView::OnInitialUpdate() { CFormView::OnInitialUpdate(); // скрываем полосы прокрутки GetParentFrame()->RecalcLayout(); // это уберёт полосы прокрутки со вьюхи ResizeParentToFit(); SIZE s={0, 0}; SetScaleToFitSize(s); // далее вызовется обработчик OnPaint(), о котором ниже //... }
Также обратите внимание на одну особенность: в отладочной версии программы вызов OnPaint после выполнения SetScaleToFitSize() с параметром s={0, 0} происходит с ошибкой (программа при этом завершается). Обходится это так:
void CMyView::OnPaint() { #ifdef _DEBUG CPaintDC dc(this); #else CFormView::OnPaint(); #endif }
Или так:
void CMyView::OnPaint() { CPaintDC dc(this); }
Как нарисовать прямоугольник с вертикальным цветовым градиентом?
Нужно задать граничные значения цветов, затем равномерно нарисовать несколько прямоугольников постепенно меняющегося цвета. Количество прямоугольников, а, значит - плавность градиента, задаётся точностью.
Пример:
// вертикальный градиент // pdc - указатель на контекст устройства // pSize - указатель на структуру // SIZE с размером прямоугольника // dwdColor1, dwdColor2 - начальный и конечный цвет // bySteps - количество шагов градиента (1...255) void sFillVertGradientRect(CDC* pdc, SIZE *pSize, COLORREF dwdColor1, COLORREF dwdColor2, BYTE bySteps) { WORD i=0; long W=0; long H=0; long x1=0; long x2=0; BYTE R1=0; BYTE G1=0; BYTE B1=0; BYTE R2=0; BYTE G2=0; BYTE B2=0; float dh=0; float dR=0; float dG=0; float dB=0; float y1=0; float y2=0; float Rc=0; float Gc=0; float Bc=0; if(!bySteps) { bySteps=1; } //ширина и высота W=pSize->cx; H=pSize->cy; // раскладываем цвета на их составляющие // для удобства дальнейших вычислений R1=(BYTE)((dwdColor1 & 0x000000ff) ); G1=(BYTE)((dwdColor1 & 0x0000ff00) >> 8 ); B1=(BYTE)((dwdColor1 & 0x00ff0000) >> 16 ); R2=(BYTE)((dwdColor2 & 0x000000ff) ); G2=(BYTE)((dwdColor2 & 0x0000ff00) >> 8 ); B2=(BYTE)((dwdColor2 & 0x00ff0000) >> 16 ); // высота разноцветных прямоугольников dh=(float)H / (float)bySteps; // величина шагов составляющих цветов dR=(float)(R2 - R1) / (float)bySteps; dG=(float)(G2 - G1) / (float)bySteps; dB=(float)(B2 - B1) / (float)bySteps; // выводим прямоугольники x1=0; x2=W; y1=0; y2=dh; Rc=R1; Gc=G1; Bc=B1; for(i=0; i<bySteps; i++) { // текущий цвет pdc->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; } }
Пример вызова:
SIZE Size={100, 100}; sFillGradientRect(&dc, &Size, RGB(200,0,0), RGB(0,200,0), 10);
Как под Windows отслеживать изменение файла?
Нужно использовать функции:
- FindFirstChangeNotification
- FindNextChangeNotification
- FindCloseChangeNotification
(подробности - в MSDN)
Как конвертировать массив char[] в CString?
Это можно сделать методами самого класса CString:
char buf[]="text"; // строка должна обязательно заканчиваться нулём!!! // конвертируем так CString txt(buf); // или так CString txt; txt=buf;
Как зарезервировать в CString буфер нужной длины?
Это можно сделать при помощи методов класса:
CString::GetBuffer(...);
и
CString::GetBufferSetLength(...);
Разница между GetBuffer(nLen) и GetBufferSetLength(nLen) в том, что первый возвращает строку не меньше заданной длины, а второй возвращает строку, точно равную заданной длине. Обе могут перераспределять память, если необходимо. В обычных случаях лучше использовать GetBuffer.
Если содержимое буфера менялось, то после этого нужно вызвать CString::ReleaseBuffer с указанием новой длины. Значение -1 в вызове CString::ReleaseBuffer означает, что длина строки будет вычислена автоматом (функцией strlen) в методе. "-1" удобно использовать, если известно, что строка заканчивается нулем.
Как передать больше одного параметр в процедуру потока?
Для этого нужно определить структуру со всеми параметрами (или указателями на них), которые нужно передать. А в процедуру потока передать лишь указатель на заполненную структуру.
Пример:
struct mystr { CEdit* pEd; CDialog* pDlg; DWORD* pdwd; int *pn; };
запуск потока:
mystr *pparam=new mystr; // экземпляр не должен быть временным!!! memset(pparam, 0, sizeof(*pparam)); pparam->pEd=...; pparam->pdwd=...; ::AfxBeginThread(thread, pparam); // тут экземпляр *(pparam) уже нельзя использовать в нашем примере, так как // он у нас удалился в процедуре потока
Процедура потока:
// поток: UINT threadLoader(LPVOID pParam) { // копируем данные из структуры в локальную структуру mystr data=*((mystr*)pParam); // освобождаем память временной структуры delete ((mystr*)pParam); pParam=0; ... data.pDlg->...; (*data.pdwd)=...; ... }
Как убрать главное меню из окна CMainFrame?
Это можно сделать в виртуальной функции PreCreateWindow:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { // обнуляем хендл меню до вызова CFrameWnd::PreCreateWindow cs.hMenu=0; if(!CFrameWnd::PreCreateWindow(cs)) { return FALSE; } ... }
Как работающая программа может определить, что пользователь завершает работу Windows?
Когда пользователь завершает работу Windows, всем процессам посылается сообщение WM_QUERYENDSESSION. Его нужно отловить в обработчике OnQueryEndSession(). Если вернуть из обработчика значение 0, то Windows продолжит работу.
Как сделать всплывающую подсказку для класса CWnd и классов, от него производных?
Допустим, имеется диалог класса CMyDlg. Делаем подсказки для элементов управления (для элементов управления CStatic не забудьте поставить свойство Notify):
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(); // создаём элемент TOOLTIP 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); }
Как в отладчике Visual С++ просмотреть содержимое std::vector<string>?
Это можно сделать так: к примеру, имеется:
std::vector<string> V;
В режиме отладки открываем окно "Watch" (ALT+3) и вставляем выражения:
- "V._Myfirst" - будет показан первый элемент V
- "V._Myfirst+1" - второй элемент V
- и так далее
Как при выводе текста на контекст устройства определить ширину и высоту выведенных символов текста в пикселах?
Для этого нужно использовать процедуру API:
BOOL GetTextExtentPoint32( HDC hdc, // хендл контекста LPCTSTR lpString, // выводимая строка int cbString, // длина строки в символах LPSIZE lpSize // указатель на структуру SIZE, куда будут помещены размеры );
Функция вычисляет ширину строки символов, оканчивающейся нулём. Поэтому, чтобы вычислить габариты многострочного текста, текст, в начале, необходимо разбить на строки, разделённые символами '\r' и '\n', и определить ширину и высоту каждой отдельно взятой строки.