FAQ:WinAPI, VCPP Part 2 — различия между версиями
RXL (обсуждение | вклад) (Категория FAQ) |
|||
Строка 757: | Строка 757: | ||
); | ); | ||
</pre> | </pre> | ||
+ | |||
+ | [[Category:FAQ]] |
Версия 21:23, 8 апреля 2008
Содержание
- 1 У меня в программе имеется процедура, которая производит очень много вычислений. Как сделать так, чтобы пользователь мог прервать процесс вычислений?
- 2 не могу обратиться к COM из дополнительного потока, мне пишут- "CoInitialize() не вызвано"
- 3 Как при открытии CFileDialog можно было выбирать только папки?
- 4 как в CDialog-based классе получить коды клавиш которые нажимает пользователь? Пробовал добавлять обработчики OnChar() и OnKeyDown(), эти обработчики вообще не вызываются
- 5 Мне нужно удалить контрол (CComboBox) с диалога, причём это надо сделать из обработчика сообщения этого контрола.
- 6 Я создал простой проект DLL на VC++ 6.0. Все скомпилилось нормально. Но в другой программе не могу вызвать функцию из DLL - программа не может найти функцию по имени.
- 7 Есть ли какой-нибудь макрос в VC7, возвращающий строку вида ClassName::FunctionName внутри соответствующей функции?
- 8 Как динамически подгрузить ресурсы к ATL проекту?
- 9 Как динамически подгрузить ресурсы к MFC проекту?
- 10 возможно ли использование файлов чистого С и С++ в одном проекте? Если да, то каковы должны быть настройки компилятора? А то ругается на Unexpected end of file while looking for precompiled header directive.
- 11 где найти описание nmake для VC++6?
- 12 Каким образом можно установить значение переменной для вызывающего процесса/потока из своей собственной DLL ? Проблема заключается в том, что несмотря на то, что все линкуется нормально, значение переменной процесса не изменяется, когда я его устанавливаю вручную в библиотеке.
- 13 Как закрасить фон окна CWnd ?
- 14 Как определить , что курсор мыши вышел за границу окна ?
- 15 Когда размещаю компонент RichEdit на форму, программа запускается и тут же закрывается. Что здесь не так?
- 16 Как сделать обработчик сообщения для нескольких контролов сразу?
- 17 Когда запускаю программу, то все надписи на русском языке теряются - показываются вопросики. Что делать?
- 18 Как проекте VC6 MFC получить путь, откуда запущен ЕХЕ ?
- 19 Как получить доступ к контролам на панели CReBar, принадлежащей классу MainFrame?
- 20 Как загрузить и показать один из стандартных курсоров?
- 21 Как запретить пользователю закрыть программу нажатием на крестик?
- 22 Как создать на диалоге группу RadioButton-ов и как задать порядок их обхода клавишей Tab?
- 23 Где лучше устанавливать начальные значения CComboBox?
- 24 Как перевести RichEdit в режим замены символов?
- 25 Как вызвать метод класса CMainFrame (главное окно) из любого места программы?
- 26 Как запретить появление полос прокруток на CFormView, когда пользователь делает размер главного окна меньше размера окна CFormView ?
- 27 Как нарисовать прямоугольник с вертикальным цветовым градиентом ?
- 28 Как под Windows отслеживать изменение файла?
- 29 Есть массив char[] , как сконвертировать его в CString ?
- 30 Как зарезервировать в CString буфер нужной длины?
- 31 Как передать больше одного параметр в процедуру потока?
- 32 Как убрать главное меню из CMainFrame ?
- 33 Как работающая программа может определить, что юзер завершает работу Windows?
- 34 Как сделать всплывающую подсказки для класса CWnd и классов, от него производных?
- 35 Как в отладчике VС просмотреть содержимое std::vector<string> V
- 36 Я вывожу на контекст устройства текст. Как определить в пикселах ширину и высоту выведенных символов текста?
У меня в программе имеется процедура, которая производит очень много вычислений. Как сделать так, чтобы пользователь мог прервать процесс вычислений?
1) В общем случае решение такое: вычисления производятся в одном потоке (T1) процесса, а обработка команд пользователя - в другом (T2). Одним из потоков может являться и основной поток. Поток T2, получив команду пользователя, выставляет определённый флаг (переменную,событие), доступный также и потоку T1. Поток T1, проверив флаг в определённый момент, прекращает/приостанавливает/продолжает свою работу. Естественно, скорость реакции T1 зависит от характера вычислений. Самый приятный вариант - вычисления, выполняемые в цикле, который часто повторяется. Тогда в начале или в конце цикла поток T1 просто проверяет флаг и принимает решение.
2) Есть ещё "ленивое решение" (подойдёт для простеньких приложений): вычисления выполняются в основном потоке, и также в начале цикла проверяется флаг. А кроме того, перед проверкой флага выполняется такой код:
//выполнить N сообщений из очереди сообщений int imsg; MSG m; for(imsg=0;imsg<N;imsg++) { //выборка,выполнение и удаление одного сообщения //из очереди сообщений всех окон данного потока if(::PeekMessage(&m,0,0,0,PM_REMOVE)) { //транслирование виртуальных клавиш ::TranslateMessage(&m); //обработка сообщения ::DispatchMessage(&m); } }
то есть будут обрабатываться все сообщения, в частности нажатия кнопок. Правда с тормозами. Тормоза можно попробовать регулировать числом N.
Примечание В любом случае необходимо тщательно продумать вариант, когда пользователь попытается закрыть программу во время вычислений :) Самое простое: в главном окне программы перехватить WM_CLOSE и разрешить закрытие программы, либо вывести предупреждение и продолжить работу.
не могу обратиться к COM из дополнительного потока, мне пишут- "CoInitialize() не вызвано"
нужно вызывать CoInitialize() в каждом новом потоке
Как при открытии CFileDialog можно было выбирать только папки?
Никак, он этого не делает. Для того, чтобы выбирать директории применяют функцию SHBrowseForFolder.
простой пример
char pchSelectedF[MAX_PATH]=""; BROWSEINFO bi= { m_hWnd, 0, pchSelectedF, "Выбираем папку", 0,0,0,0 }; SHBrowseForFolder(&bi); //bi.pszDisplayName - выбранная папка
как в CDialog-based классе получить коды клавиш которые нажимает пользователь? Пробовал добавлять обработчики OnChar() и OnKeyDown(), эти обработчики вообще не вызываются
Диалоги действительно не обрабатывают OnChar() и OnKeyDown(), Поэтому нужно ловить сообщения WM_CHAR и WM_KEYDOWN в виртуальной PreTranslateMessage()
BOOL CMyDialog::PreTranslateMessage(MSG* pMsg) { if(pMsg->message==WM_KEYDOWN) { // pMsg->wParam - код клавиши // pMsg->hwnd - хендл контрола окна, который получил сообщение // pMsg->lParam - дополнительная информация: //биты 0...15 - количество повторов //биты 16...23 - скан-код //бит 24 -установлен, если нажат правый Ctrl } if(pMsg->message==WM_CHAR) { //pMsg - всё аналогично WM_KEYDOWN } return CDialog::PreTranslateMessage(pMsg); }
===имеется непрерывный участок памяти M. 1) как заполнить M определённым значением? 2) как сравнить два участка памяти M1 и M2 на равенство значений? 3) как скопировать участок M1 в M2 ?=== 1) заполнить участок памяти длиной N байтов можно функцией
void* memset(void* pM, int val, size_t N);
или при помощи макроса
ZeroMemory(Destination,Length);//использует memset FillMemory(Destination,Length,Fill);//использует memset
2) сравнить два участка памяти длиной N байтов можно функцией
int memcmp(const void* pM2, const void* pM1, size_t N);
memcmp возвращает 0, если участки памяти идентичны.
3) как скопировать участок M1 длиной N байтов в M2 можно функцией
void* memcpy(void* pM2, const void* pM1, size_t N); void* memmove(void* pM2, const void* pM1, size_t N);
или при помощи макросов
CopyMemory(Destination,Source,Length);//использует MoveMemory(Destination,Source,Length);
Если участки памяти перекрываются, то результат работы memcpy не определён. Функция memmove гарантирует правильное копирование даже при перекрывающихся участках
Примечание: Правильность переданных параметров в функциях, естественно, не проверяется.
Мне нужно удалить контрол (CComboBox) с диалога, причём это надо сделать из обработчика сообщения этого контрола.
Вот так вылетает ошибка:
void CMyDialog::OnSelchange() { CComboBox* m_pControl=(CComboBox*)GetDlgItem(IDC_MYCOMBO); m_pControl->DestroyWindow(); }
Удалять объект из принадлежащего ему обработчика нельзя. Нужно удалить объект после завершения обработчика. Например можно послать в диалого-родитель некое сообщение, в обработчике которого и удалить контрол.
Например:
enum { e_command_delete = WM_USER+1, }; void CMyDialog::OnSelchange() { //CComboBox* m_pControl=(CComboBox*)GetDlgItem(IDC_MYCOMBO); //m_pControl->DestroyWindow(); //кладём в очередь сообщений своё сообщение PostMessage(WM_COMMAND,(e_command_delete<<16) |IDC_MYCOMBO ,0x5555); } BOOL CMyDialog::OnCommand(WPARAM wParam, LPARAM lParam) { if((wParam>>16)==e_command_delete) { if(((WORD)wParam)==IDC_MYCOMBO) { CComboBox* m_pControl=(CComboBox*)GetDlgItem(IDC_MYCOMBO); m_pControl->DestroyWindow(); return 1; } } return CDialog::OnCommand(wParam, lParam); }
Я создал простой проект DLL на VC++ 6.0. Все скомпилилось нормально. Но в другой программе не могу вызвать функцию из DLL - программа не может найти функцию по имени.
В папке проекта нужно создать обычный файл txt и переименовать в "имя_проекта_dll.DEF"
В файле перечислить весь экспорт:
EXPORTS MyFunctionName1 MyFunctionName2 MyFunctionName3
И затем включить файл этот в дерево проекта.
Есть ли какой-нибудь макрос в VC7, возвращающий строку вида ClassName::FunctionName внутри соответствующей функции?
__FUNCSIG__
Как динамически подгрузить ресурсы к ATL проекту?
имеется класс Код:
class CComModule : public _ATL_MODULE
в котором определена переменная m_hInstResource. Нужно присвоить переменной значение хэндла Dll.
Как динамически подгрузить ресурсы к MFC проекту?
InitInstance() загружается Dll с ресурсами, затем вызывается функция AfxSetResourceHandle c параметром - хэндлом этой dll.
BOOL CMyApp::InitInstance() { HINSTANCE hRes = NULL; hRes= LoadLibrary("ResourceD.dll"); if(hRes) { AfxSetResourceHandle(hRes); } return CWinApp::InitInstance(); }
возможно ли использование файлов чистого С и С++ в одном проекте? Если да, то каковы должны быть настройки компилятора? А то ругается на Unexpected end of file while looking for precompiled header directive.
Компилятор распознает язык по расширению файла и устанавливает на весь файл. Нельзя часть файла компилировать как С, а другую как С++. Для того, чтобы Сишные функции вызывать в С++, а С++ в С, их надо декларировать для С++ как
extern "C" #ifdef __cplusplus extern "C" { #endif int func1(int ); int func2(int ); int func3(int ); #ifdef __cplusplus } #endif
Возможно, надо стереть *.pch файл и собрать снова.
Также в настройках компилятора можно попробовать отключить прекомпиленые хедеры для конкретного файла-
"C/С++"->"Precompiled Header"
(правда перекомпиляция будет длится немного дольше)
Или можно подключить в файлах stdafx.h (тогда не придется отключать use precompiled header )
где найти описание nmake для VC++6?
В MSDN http://msdn.microsoft.com/library/en-us/vcug98/html/_asug_overview.3a_.nmake_reference.asp
Каким образом можно установить значение переменной для вызывающего процесса/потока из своей собственной DLL ? Проблема заключается в том, что несмотря на то, что все линкуется нормально, значение переменной процесса не изменяется, когда я его устанавливаю вручную в библиотеке.
Проблема вызвана тем, что каждая влинкованная libc (одна линкуется в исполняемый файл, ещё одна в dll) содержит свою копию переменной.
1) Можно воспользоваться динамически подгружаемой библиотекой С runtime. Для этого приложение и dll надо компилировать с ключом /MD (или MDd для отладки). В таком случае переменная будет общей для приложения и dll.
2) Можно в основном модуле программы (тот, который станет .exe) сделать "дырку" (backdoor), через которую присваивать переменной (int errno) значение:
__declspec(dllexport) void set_errno(int code) { errno = code; }
В dll при подключении к процессу надо извлечь из модуля программы указатель на эту функцию.
typedef void (*SETINT)(int); SETINT g_set_errno=0; void set_errno_in_exe(int code) { if(g_set_errno) g_set_errno(code); } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) { HANDLE hModule; // Handle to the main module if(fdwReason == DLL_PROCESS_ATTACH ) { hModule = GetModuleHandle(NULL); if (hModule == NULL) return FALSE; g_set_errno = (SETINT) GetProcAddress(hModule, "set_errno"); } return TRUE; }
В нужном месте в dll вместо присваивания errno нужно вызывать внешнюю функцию
void inside_dll_func() { ... ... set_errno_in_exe(ERROR_CODE); ... }
Как закрасить фон окна CWnd ?
Нужно добавить обработчик сообщения WM_CTLCOLOR
class CMyDialog : public CDialog { // CBrush m_back_brush; ... ... }; //конструктор CMyDialog::CMyDialog(): CDialog(CMyDialog::IDD) { //создаём кисть фона m_back_brush.CreateSolidBrush(RGB(192,186,207)); }
HBRUSH CMyDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { switch(nCtlColor) { //CStatic-контрол case WM_CTLCOLORSTATIC: { //у статиков делаем прозрачный фон pDC->SetBkMode(TRANSPARENT); //и красный цвет текста pDC->SetTextColor(RGB(255,0,0)); //надо же что-то вернуть :) return (HBRUSH) (m_back_brush.m_hObject); } break; //диалог case WM_CTLCOLORDLG: { //возвращаем хендл кисти нужного фона return (HBRUSH) (m_back_brush.m_hObject); } break; } //фон по умолчанию return CDialog::OnCtlColor(pDC, pWnd, nCtlColor); }
Как определить , что курсор мыши вышел за границу окна ?
1) способ первый Использовать функцию _TrackMouseEvent. Например, есть класс MyST
class MyST : public CStatic { bool m_bTrackingNow; ... ... }; //в конструкторе MyST:MyST() { m_bTrackingNow=false; } //в обработчике OnMouseMove запускаем отслеживание void MyST::OnMouseMove(UINT nFlags, CPoint point) { if(!m_bTrackingNow) { m_bTrackingNow=true; TRACKMOUSEEVENT tme; tme.cbSize=sizeof(tme); tme.dwFlags=TME_LEAVE;//отслеживаем выход курсора tme.hwndTrack = m_hWnd;//из этого окна ::_TrackMouseEvent(&tme);//"запуск" отслеживания //при выходе курсора за границу окна будет //будет сгенерировано сообщение WM_MOUSELEAVE } ... ... CStatic::OnMouseMove(nFlags,point); } //ловим сообщение WM_MOUSELEAVE, для этого //переопределяем виртуальную PreTranslateMessage() BOOL MyST::PreTranslateMessage(MSG* pMsg) { if(pMsg->message==WM_MOUSELEAVE) { //тут обрабатываем ... ... m_bTrackingNow=false; } ... ... return CStatic::PreTranslateMessage(pMsg); }
2) способ дыва, для случая, когда надо регулировать время "реакции" на выход за границу
enum { def_TrackTimer_ID = 1000, //ID таймера def_TrackTimer_value = 50, //миллисекунд }; MyST::MyST() { m_bTrackingNow=false; } //в обработчике OnMouseMove запускаем таймер void MyST::OnMouseMove(UINT nFlags, CPoint point) { //перезапуск таймера SetTimer(def_TrackTimer_ID,def_TrackTimer_value,0); m_bTrackingNow=true; ... ... CStatic::OnMouseMove(nFlags,point); } void MyST::OnTimer(UINT nIDEvent) { if(nIDEvent==def_TrackTimer_ID) { KillTimer(def_TrackTimer_ID);//таймер гасит сам себя //смотрим, где курсор POINT pnt; if(GetCursorPos(&pnt)) { if(WindowFromPoint(pnt)!=this) { m_bTrackingNow=false;//вышли за окно } } } CStatic::OnTimer(nIDEvent); }
Когда размещаю компонент RichEdit на форму, программа запускается и тут же закрывается. Что здесь не так?
Необходимо до начала использования контрола инициализировать работу с классом:
для RichEdit необходимо вызвать функцию AfxInitRichEdit(), для RichEdit2 - AfxInitRichEdit2().
Вызывать надо в InitInstance() приложения (в случае для MFC).
Как сделать обработчик сообщения для нескольких контролов сразу?
Если без помощи визарда, то переопределить виртуальную OnCommand()
BOOL CMyDialog::OnCommand(WPARAM wParam, LPARAM lParam) { WORD wMess=(wParam>>16);//командное сообщение int nID=(int)(wParam &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); }
Когда запускаю программу, то все надписи на русском языке теряются - показываются вопросики. Что делать?
Лечится так: непосредственно после создания проекта открываем дерево ресурсов и в свойствах каждого элемента дерева ставим язык 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() - в главное окно программы. Для диалоговых приложений - это главный диалог, для одно- и много-документных - это CMainFrame.
void CMainFrame::OnClose() { if(......) { //не разрешаем закрыть return; } CFrameWnd::OnClose(); }
Как создать на диалоге группу 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()->m_pMainWnd-> ... ;
Как запретить появление полос прокруток на CFormView, когда пользователь делает размер главного окна меньше размера окна CFormView ?
методом SetScaleToFitSize()
void CMyView::OnInitialUpdate() { CFormView::OnInitialUpdate(); ///////// GetParentFrame()->RecalcLayout(); ResizeParentToFit(); SIZE s={0,0}; SetScaleToFitSize(s); ///////// ... ... }
Как нарисовать прямоугольник с вертикальным цветовым градиентом ?
pdc - указатель на контекст устройства pSize - указатель на структуру SIZE с размером прямоугольника dwdColor1, dwdColor2 - начальный и конечный цвет bySteps - количество шагов градиента (1...255)
//вертикальный градиент 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->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)-((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<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
Есть массив char[] , как сконвертировать его в CString ?
char buf[]="text"; //строка должна быть обязательно заканчиваться нулём. //конвертируем так CString txt(buf); //или так CString txt; txt=buf;
Как зарезервировать в CString буфер нужной длины?
при помощи метоодов класса:
CString::GetBuffer и CString::GetBufferSetLength
Разница между CString::GetBuffer(nLen) и CString::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);//подчищаем память ... data.pDlg->...; (*data.pdwd)=...; ... }
Как убрать главное меню из CMainFrame ?
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { //обнуляем хендл меню до вызова CFrameWnd::PreCreateWindow cs.hMenu = 0; if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; ... ... }
Как работающая программа может определить, что юзер завершает работу 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(); // //создаём 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); }
Как в отладчике VС просмотреть содержимое std::vector<string> V
В режиме отладки открываем окно "Watch" (ALT+3) и вставляем выражения:
V._Myfirst - будет показан первый элемент V._Myfirst+1 - второй V._Myfirst+2 - и т.д.
Я вывожу на контекст устройства текст. Как определить в пикселах ширину и высоту выведенных символов текста?
использовать процедуру API
BOOL GetTextExtentPoint32( HDC hdc,// хендл контекста LPCTSTR lpString,// выводимая строка int cbString,// длина строки в символах LPSIZE lpSize// указатель на структуру SIZE, куда //будут помещены размеры );