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

Материал из Весельчак У
Перейти к: навигация, поиск
Строка 1: Строка 1:
 
 
=== Как узнать, что пользователь меняет текст в приложении на основе CRichEditView?===
 
=== Как узнать, что пользователь меняет текст в приложении на основе CRichEditView?===
 
Нужно добавить обработчик сообщения EN_CHANGE. Сообщение генерируется CRichEditView каждый раз, когда пользователь изменяет текст в окне CRichEditView
 
Нужно добавить обработчик сообщения EN_CHANGE. Сообщение генерируется CRichEditView каждый раз, когда пользователь изменяет текст в окне CRichEditView
Строка 8: Строка 7:
 
===Как загрузить текстовую строку из ресурса?===
 
===Как загрузить текстовую строку из ресурса?===
 
Пример:
 
Пример:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
CString m_Temp;
 
CString m_Temp;
 
m_Temp.LoadString(ID_MYSTRING);
 
m_Temp.LoadString(ID_MYSTRING);
Строка 15: Строка 14:
 
===Как поменять иконку у элемента item в CListCtrl?===
 
===Как поменять иконку у элемента item в CListCtrl?===
 
Пример:
 
Пример:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
//заполняем структуру LVITEM
 
//заполняем структуру LVITEM
 
LVITEM lvItem;
 
LVITEM lvItem;
 
memset(&lvItem,0,sizeof(lvItem));
 
memset(&lvItem,0,sizeof(lvItem));
 
 
lvItem.mask = LVIF_IMAGE;//меняться будет картинка
+
lvItem.mask =LVIF_IMAGE;//меняться будет картинка
lvItem.iItem = ...;// индекс элемента списка (Zero-based)
+
lvItem.iItem =...;// индекс элемента списка (Zero-based)
lvItem.iSubItem = 0;
+
lvItem.iSubItem =0;
lvItem.iImage = ...; //индекс иконки (из списка контрола)
+
lvItem.iImage =...; //индекс иконки (из списка элемента)
 
 
 
pList->SetItem(&lvItem);
 
pList->SetItem(&lvItem);
 
</syntaxhighlight>
 
</syntaxhighlight>
  
===Имеется класс Class1, содержащий мембер типа "указатель на Class2". В Class2 также имеется указатель на Class1. Компилятор выдаёт ошибку. Что надо делать?===
+
===Имеется класс Class1, содержащий член типа "указатель на Class2". В Class2 также имеется указатель на Class1. Компилятор выдаёт ошибку. Что надо делать?===
Перекрёстное определение обходится следкющим образом: код обоих классов разносится в пары файлов *.h и *.cpp, а перед каждым классом вписывается предопределение другого класса:
+
Перекрёстное определение обходится следующим образом: код обоих классов разносится в пары файлов *.h и *.cpp, а перед каждым классом вписывается предопределение другого класса:
  
  
 
файл "class1.h"
 
файл "class1.h"
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
class Class2;//предопределение Class2
 
class Class2;//предопределение Class2
  
Строка 46: Строка 45:
  
 
файл "class1.cpp"
 
файл "class1.cpp"
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
#include "class1.h"
 
#include "class1.h"
 
#include "class2.h"
 
#include "class2.h"
Строка 63: Строка 62:
  
 
файл "class2.h"
 
файл "class2.h"
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
class Class1;//предопределение Class1
 
class Class1;//предопределение Class1
  
Строка 76: Строка 75:
  
 
файл "class2.cpp"
 
файл "class2.cpp"
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
#include "class2.h"
 
#include "class2.h"
 
#include "class1.h"
 
#include "class1.h"
Строка 87: Строка 86:
  
  
После предопределениея класса компилятор позволяет объявлять указатель на класс, так как переменная указателя на любой тип имеет всегда один и тот же размер.
+
После предопределения класса компилятор позволяет объявлять указатель на класс, так как переменная указателя на любой тип имеет всегда один и тот же размер.
  
 
===Как переключить раскладку в другом (то есть в активном) процессе?===
 
===Как переключить раскладку в другом (то есть в активном) процессе?===
 
Для этого можно использовать функции
 
Для этого можно использовать функции
<syntaxhighlight>
+
 
GetKeyboardLayout(...); // определить текущую раскладку
+
* GetKeyboardLayout(...); // определить текущую раскладку
LoadKeyboardLayout(...); // загрузить новую раскладку
+
* LoadKeyboardLayout(...); // загрузить новую раскладку
VerLanguageName(...); // получить строку с описанием языка
+
* VerLanguageName(...); // получить строку с описанием языка
</syntaxhighlight>
+
  
 
Подробности - в MSDN
 
Подробности - в MSDN
Строка 103: Строка 101:
 
Пусть элемент Edit лежит на окне CMyWnd.
 
Пусть элемент Edit лежит на окне CMyWnd.
 
Тогда:
 
Тогда:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
void CMyWnd::некая_процедура()
 
void CMyWnd::некая_процедура()
 
{
 
{
Строка 127: Строка 125:
  
 
через указатель на родительское окно:
 
через указатель на родительское окно:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
pParent->PostMessage(WM_CLOSE);
 
pParent->PostMessage(WM_CLOSE);
 
</syntaxhighlight>
 
</syntaxhighlight>
  
при помощи хендла рордительского окна:
+
при помощи хендла родительского окна:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
::PostMessage(pParent->m_hWnd,WM_CLOSE,(WPARAM)0,(LPARAM)0);
 
::PostMessage(pParent->m_hWnd,WM_CLOSE,(WPARAM)0,(LPARAM)0);
 
</syntaxhighlight>
 
</syntaxhighlight>
Строка 138: Строка 136:
 
===Как корректно перевести тип BSTR в CString и наоборот?===
 
===Как корректно перевести тип BSTR в CString и наоборот?===
  
1) для конвертирования BSTR в CString нужно просто присвоить переменной типа CString переменную типа BSTR.
+
# для конвертирования BSTR в CString нужно просто присвоить переменной типа CString переменную типа BSTR.
 
Оператор "=" класса CString сам выполнит всю работу.
 
Оператор "=" класса CString сам выполнит всю работу.
  
2) для конвертирования BSTR в CString нужно выполнить код:
+
# для конвертирования BSTR в CString нужно выполнить код:
<syntaxhighlight>
+
  
 +
<syntaxhighlight lang="cpp">
 
//указатель на будущий буфер с BSTR.
 
//указатель на будущий буфер с BSTR.
 
BSTR bstrHE=0;
 
BSTR bstrHE=0;
Строка 168: Строка 166:
 
Для этого нужно использовать функции
 
Для этого нужно использовать функции
  
<syntaxhighlight>
+
* OpenThemeData(...);
OpenThemeData(...);
+
* DrawThemeBackground(...);
DrawThemeBackground(...);
+
* DrawFrameControl(...);
DrawFrameControl(...);
+
* CloseThemeData(...);
CloseThemeData(...);
+
</syntaxhighlight>
+
  
 
(подробности - в MSDN)
 
(подробности - в MSDN)
  
===Имеется класс , производный от CDialog. Когда диалог в фокусе, нажатие на Enter или Esc приводит к закрытию диалога. Как это запретить?===
+
===Имеется класс, производный от CDialog. Когда диалог в фокусе, нажатие на Enter или Esc приводит к закрытию диалога. Как это запретить?===
 
При нажатии Enter происходит выполнение команды IDOK,при нажатии Esc - IDCANCEL.
 
При нажатии Enter происходит выполнение команды IDOK,при нажатии Esc - IDCANCEL.
  
Строка 185: Строка 181:
  
 
Однако тогда диалог станет невозможно закрыть кнопкой с крестиком. Это обходится так: добавляем обработчик сообщения WM_CLOSE - OnClose(), и в нём делаем вызов OnOk() или OnCancel():
 
Однако тогда диалог станет невозможно закрыть кнопкой с крестиком. Это обходится так: добавляем обработчик сообщения WM_CLOSE - OnClose(), и в нём делаем вызов OnOk() или OnCancel():
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
void CPlayersPropsDialog::OnClose()  
 
void CPlayersPropsDialog::OnClose()  
 
{
 
{
Строка 193: Строка 189:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
===Я написал в VC++ простейший макрос , где невозможно ошибиться, а компилятор всё же выдаёт ошибку. Не пойму, в чём дело?===
+
===Я написал в VC++ простейший макрос, где невозможно ошибиться, а компилятор всё же выдаёт ошибку. Не пойму, в чём дело?===
  
Скорее всего после одного из символов соединения строк "\" имеется пробел или табуляция. Их надо удалить. Можно найти их "наощупь", а можно включить показ непечатных символов в студии. Найти эту команду можно так:
+
Скорее всего после одного из символов соединения строк "\" имеется пробел или табуляция. Их надо удалить. Можно найти их "на ощупь", а можно включить показ непечатных символов в студии. Найти эту команду можно так:
  
 
Tools->Customize...->вкладка Commands. В окошке Category выбрать "Edit", и среди кнопок справа найти кнопку, на которой написано "a.b"
 
Tools->Customize...->вкладка Commands. В окошке Category выбрать "Edit", и среди кнопок справа найти кнопку, на которой написано "a.b"
Строка 201: Строка 197:
 
Эту кнопку надо перетащить на одну из панелей инструментов студии.
 
Эту кнопку надо перетащить на одну из панелей инструментов студии.
  
===Как получить список всех процесов, включая idle?===
+
===Как получить список всех процессов, включая idle?===
  
 
Использовать функции
 
Использовать функции
<syntaxhighlight>
+
* Process32First(...);
Process32First(...);
+
* Precess32Next(...);
Precess32Next(...);
+
</syntaxhighlight>
+
  
 
(подробности - в MSDN)
 
(подробности - в MSDN)
Строка 213: Строка 207:
 
===Как программно установить переменные окружения?===
 
===Как программно установить переменные окружения?===
 
Чтобы добавить или изменить их программно, необходимо воспользоваться ключом реестра
 
Чтобы добавить или изменить их программно, необходимо воспользоваться ключом реестра
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment
+
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
Затем нужно отправить широковещательное сообщение WM_SETTINGCHANGE (это позволит приложениям узнать об изменениях):
 
Затем нужно отправить широковещательное сообщение WM_SETTINGCHANGE (это позволит приложениям узнать об изменениях):
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
::SendMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0);
+
::SendMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0);
 
</syntaxhighlight>
 
</syntaxhighlight>
  
  
 
===Как сделать, чтобы у окна был черный фон?===
 
===Как сделать, чтобы у окна был черный фон?===
Нужно переопределить обработчик сообщения WM_CTLCOLOR - OnCtlColor() :
+
Нужно переопределить обработчик сообщения WM_CTLCOLOR - OnCtlColor():
 +
 
 +
<syntaxhighlight lang="cpp">
 +
//глобальная переменная или член класса CMyDlg,
 +
// инициализированный в OnInitDialog()
 +
CBrush br(RGB(0,0,0));
 +
 
  
<syntaxhighlight>
 
CBrush br(RGB(0,0,0)); //глобальная переменная или член класса CMyDlg,
 
// инициализированный в OnInitDialog()
 
 
 
HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
 
HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
 
{
 
{
Строка 253: Строка 249:
  
 
===Почему на моем компьютере экзешник, созданный в MFC запускается, а на других компьютерах - нет? Требует какую-то  dll-ку.===
 
===Почему на моем компьютере экзешник, созданный в MFC запускается, а на других компьютерах - нет? Требует какую-то  dll-ку.===
Нужно выбирать режим Release :
+
Нужно выбирать режим Release:
  
 
Menu->Build->Configurations...->Release,
 
Menu->Build->Configurations...->Release,
Строка 262: Строка 258:
 
Нужно создать в редакторе ресурсов новое меню, затем вставить его в диалог:
 
Нужно создать в редакторе ресурсов новое меню, затем вставить его в диалог:
  
1)открыть в редакторе диалог,
+
# открыть в редакторе диалог,
 
+
# в свойствах (во вкладке General, окошко Menu) указать идентификатор ресурса меню.
2)в свойствах (во вкладке General, окошко Menu) указать идентивикатор ресурса меню.
+
# при помощи визарда добавить для меню обработчики OnCommand() и OnUpdateСommand().
 
+
3)при помощи визарда добавить для меню обработчики OnCommand() и OnUpdateСommand().
+
  
 
===Почему не вызывается OnUpdate для пунктов меню (не получается ни затенить, ни отметку поставить)?===
 
===Почему не вызывается OnUpdate для пунктов меню (не получается ни затенить, ни отметку поставить)?===
Строка 272: Строка 266:
  
 
Визардом этот обработчик не добавляется, поэтому можно переопределить виртуальную DefWindowProc() и там обработать:
 
Визардом этот обработчик не добавляется, поэтому можно переопределить виртуальную DefWindowProc() и там обработать:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
#include <afxpriv.h> //этот файл надо включить, там определёна WM_KICKIDLE
 
#include <afxpriv.h> //этот файл надо включить, там определёна WM_KICKIDLE
  
Строка 284: Строка 278:
 
{
 
{
 
CCmdUI cmdUI;
 
CCmdUI cmdUI;
for (UINT n=0; n < pMainMenu->GetMenuItemCount(); ++n)
+
for(UINT n=0; n < pMainMenu->GetMenuItemCount(); n++)
 
{
 
{
 
CMenu* pSubMenu = pMainMenu->GetSubMenu(n);
 
CMenu* pSubMenu = pMainMenu->GetSubMenu(n);
Строка 290: Строка 284:
 
 
 
cmdUI.m_nIndexMax = pSubMenu->GetMenuItemCount();
 
cmdUI.m_nIndexMax = pSubMenu->GetMenuItemCount();
for (UINT i = 0; i < cmdUI.m_nIndexMax;++i)
+
for(UINT i=0; i<cmdUI.m_nIndexMax; i++)
 
{
 
{
 
cmdUI.m_nIndex = i;
 
cmdUI.m_nIndex = i;
Строка 310: Строка 304:
  
 
Пример 1. (для SDI, MDI)
 
Пример 1. (для SDI, MDI)
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
//этот обработчик уже добавлен визардом
 
//этот обработчик уже добавлен визардом
 
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
 
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
Строка 335: Строка 329:
 
Если диалог описан в ресурсах, то в свойствах диалога убрать галочки
 
Если диалог описан в ресурсах, то в свойствах диалога убрать галочки
  
"System menu"
+
* "System menu"
 
+
* "Minimize box"
"Minimize box"
+
* "Maximize box"
 
+
"Maximize box"
+
  
 
===Как запретить пользователю нажать на кнопку?===
 
===Как запретить пользователю нажать на кнопку?===
Строка 345: Строка 337:
  
  
Пусть имеется некий диалог, на нём лежит кнопка c ID == IDC_1. В любом месте кода диалога (кроме конструктора и деструктора , хотя, если проверить наличие валидного хендла диалога, как в примере, то ничего страшного не будет и там) выполняем код
+
Пусть имеется некий диалог, на нём лежит кнопка c ID == IDC_1. В любом месте кода диалога (кроме конструктора и деструктора, хотя, если проверить наличие валидного хендла диалога, как в примере, то ничего страшного не будет и там) выполняем код
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
//делаем кнопку неактивной
 
//делаем кнопку неактивной
 
if(m_hWnd)
 
if(m_hWnd)
Строка 352: Строка 344:
 
CWnd* pw=0;
 
CWnd* pw=0;
 
pw=GetDlgItem(IDC_1);
 
pw=GetDlgItem(IDC_1);
if(pw)pw->EnableWindow(0);
+
if(pw)
 +
{
 +
pw->EnableWindow(0);
 +
}
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
===Что означают сообщения, которые студия выводит при компиляции, вроде таких : Loaded 'C:\WINDOWS\SYSTEM\WSOCK32.DLL', no matching symbolic information found. ===
+
===Что означают сообщения, которые студия выводит при компиляции, вроде таких: Loaded 'C:\WINDOWS\SYSTEM\WSOCK32.DLL', no matching symbolic information found. ===
 
Это строка говорит о том, что студия не смогла найти отладочные символы для WSOCK32.DLL. В этом нет ничего страшного, просто при наличии отладочных символов в процессе отладки можно получить доступ к именам функции из системных DLL. Например, вместо
 
Это строка говорит о том, что студия не смогла найти отладочные символы для WSOCK32.DLL. В этом нет ничего страшного, просто при наличии отладочных символов в процессе отладки можно получить доступ к именам функции из системных DLL. Например, вместо
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
KERNEL32! 0x77E8B184()
 
KERNEL32! 0x77E8B184()
 
</syntaxhighlight>
 
</syntaxhighlight>
 
увидим
 
увидим
  
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
KERNEL32!CreateThread.
 
KERNEL32!CreateThread.
 
</syntaxhighlight>
 
</syntaxhighlight>
Строка 369: Строка 364:
 
===Как обработать сообщения, которое приходит к некому элементу управления?===
 
===Как обработать сообщения, которое приходит к некому элементу управления?===
 
Скажем, нужно обработать сообщения, приходящие к элементу класса CEdit. Нужно произвести от CEdit свой класс, и в виртуальной процедуре класса WindowProc перехватить нужные сообщения.
 
Скажем, нужно обработать сообщения, приходящие к элементу класса CEdit. Нужно произвести от CEdit свой класс, и в виртуальной процедуре класса WindowProc перехватить нужные сообщения.
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
virtual LRESULT WindowProc(
 
virtual LRESULT WindowProc(
 
UINT message,
 
UINT message,
Строка 378: Строка 373:
  
 
Пример. Полностью выключаем, скажем, обработку сообщения WM_CHAR
 
Пример. Полностью выключаем, скажем, обработку сообщения WM_CHAR
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
LRESULT CMyEdit::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)  
 
LRESULT CMyEdit::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)  
 
{
 
{
Строка 394: Строка 389:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Чтобы связать экземпляр класса с элементо на форме, добавьте визардом для
+
Чтобы связать экземпляр класса с элементом управления на форме, добавьте визардом для
контрола переменную класса (выбрав не Value а Control).
+
элемента управления переменную класса (выбрав не Value а Control).
  
 
===Как настроить количество пробелов в табуляции?===
 
===Как настроить количество пробелов в табуляции?===
 
Есть пара способов:
 
Есть пара способов:
  
1) Tools->Options->Tabs->Insert Spaces
+
# Tools->Options->Tabs->Insert Spaces
 
+
# правой кнопкой мыши щёлкнуть по тексту, в контекстном меню выбрать properties
2) правой кнопкой мыши щёлкнуть по тексту, в контекстном меню выбрать properties
+
  
 
===Как автоматически расставить отступы?===
 
===Как автоматически расставить отступы?===
Строка 417: Строка 411:
 
===Как узнать количество установленных в CListCtrl столбцов?===
 
===Как узнать количество установленных в CListCtrl столбцов?===
 
Пример
 
Пример
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
//указатель на переменную-контрол
+
//указатель на переменную-элемент управления
 
CListCtrl* pL=...;
 
CListCtrl* pL=...;
  
Строка 427: Строка 421:
 
===Как получить иконку приложения?===
 
===Как получить иконку приложения?===
 
Если приложение запущено, то нужно найти его главное окно и послать ему сообщение WM_GETICON.
 
Если приложение запущено, то нужно найти его главное окно и послать ему сообщение WM_GETICON.
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
//функция возвращант хендл иконки  
 
//функция возвращант хендл иконки  
 
LRESULT SendMessage(hWnd, WM_GETICON, wParam, 0);
 
LRESULT SendMessage(hWnd, WM_GETICON, wParam, 0);
Строка 442: Строка 436:
 
===Как в CString можно найти или вырезать часть строки?===
 
===Как в CString можно найти или вырезать часть строки?===
 
Это можно сделать при помощи методов класса CString:
 
Это можно сделать при помощи методов класса CString:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
//вырезает кусок строки
 
//вырезает кусок строки
 
CString Mid(int nFirst) const;
 
CString Mid(int nFirst) const;
Строка 452: Строка 446:
  
 
//возвращает начальный кусок строки, в котором есть только
 
//возвращает начальный кусок строки, в котором есть только
//символы из набора,представленного в lpszCharSet
+
//символы из набора, представленного в lpszCharSet
 
CString SpanIncluding(LPCTSTR lpszCharSet ) const;
 
CString SpanIncluding(LPCTSTR lpszCharSet ) const;
  
 
//возвращает начальный кусок строки, в котором нет
 
//возвращает начальный кусок строки, в котором нет
//символов из набора,представленного в lpszCharSet
+
//символов из набора, представленного в lpszCharSet
 
CString SpanExcluding(LPCTSTR lpszCharSet ) const;  
 
CString SpanExcluding(LPCTSTR lpszCharSet ) const;  
  
 
//убирает "пробелоподобные" символы из самого начала строки
 
//убирает "пробелоподобные" символы из самого начала строки
//(то есть - пробел, табуляцию (\t) , возврат каретки, перевод строки (/r/n))
+
//(то есть - пробел, табуляцию (\t), возврат каретки, перевод строки (/r/n))
 
void TrimLeft();
 
void TrimLeft();
 
//убирает все повторы символа из самого начала строки
 
//убирает все повторы символа из самого начала строки
Строка 485: Строка 479:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
===Как отобразить на элементах управления промежуточные результаты длительных вичислений ?===
+
===Как отобразить на элементах управления промежуточные результаты длительных вычислений?===
 
В общем случае это делается принудительной перерисовкой нужного окна путём объявления этого окна невалидным
 
В общем случае это делается принудительной перерисовкой нужного окна путём объявления этого окна невалидным
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
pWnd->Invalidate(0);
 
pWnd->Invalidate(0);
 
</syntaxhighlight>
 
</syntaxhighlight>
 
а затем непосредственной отсылки в оконную процедуру сообщения WM_PAINT
 
а затем непосредственной отсылки в оконную процедуру сообщения WM_PAINT
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
pWnd->UpdateWindow();
 
pWnd->UpdateWindow();
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
Пример:
 
Пример:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
CWnd* pWnd=...;//окно, которое надо перерисовывать
 
CWnd* pWnd=...;//окно, которое надо перерисовывать
  
for(int i=0;i<10000)
+
for(int i=0; i<10000; i++)
 
{
 
{
 
//меняется содержимое окна
 
//меняется содержимое окна
Строка 515: Строка 509:
 
Переменные и массивы в DLL, содержимое которых должно использоваться несколькими процессами, должны объявляться статическими. Статическая переменная или массив инициализируются только один раз в момент загрузки DLL.
 
Переменные и массивы в DLL, содержимое которых должно использоваться несколькими процессами, должны объявляться статическими. Статическая переменная или массив инициализируются только один раз в момент загрузки DLL.
 
Пример:
 
Пример:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
DWORD calltest()
 
DWORD calltest()
 
{
 
{
Строка 523: Строка 517:
  
 
//будет выполняться каждый раз
 
//будет выполняться каждый раз
return ++callcount;
+
callcount++;
 +
return callcount;
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
Строка 530: Строка 525:
  
 
Создание проекции:
 
Создание проекции:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
HANDLE CreateFileMapping(
 
HANDLE CreateFileMapping(
 
HANDLE hFile, //хендл уже открытого файла
 
HANDLE hFile, //хендл уже открытого файла
 
LPSECURITY_ATTRIBUTES lpAttributes,
 
LPSECURITY_ATTRIBUTES lpAttributes,
 
DWORD flProtect, //способ открытия проекции
 
DWORD flProtect, //способ открытия проекции
DWORD dwMaximumSizeHigh, //размер файла (старшие 4 байта , обычно==0)
+
DWORD dwMaximumSizeHigh, //размер файла (старшие 4 байта, обычно==0)
 
DWORD dwMaximumSizeLow, //размер файла (младшие 4 байта)
 
DWORD dwMaximumSizeLow, //размер файла (младшие 4 байта)
 
LPCTSTR lpName
 
LPCTSTR lpName
Строка 542: Строка 537:
  
 
Доступ к созданной проекции производится процедурой:
 
Доступ к созданной проекции производится процедурой:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
LPVOID MapViewOfFile(
 
LPVOID MapViewOfFile(
 
HANDLE hFileMappingObject, //хендл проекции
 
HANDLE hFileMappingObject, //хендл проекции
Строка 555: Строка 550:
  
 
После работы с проекцией, её надо освободить процедурой
 
После работы с проекцией, её надо освободить процедурой
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
BOOL UnmapViewOfFile(
 
BOOL UnmapViewOfFile(
 
LPCVOID lpBaseAddress //адрес, который вернула процедура MapViewOfFile
 
LPCVOID lpBaseAddress //адрес, который вернула процедура MapViewOfFile
Строка 562: Строка 557:
  
 
Пример:
 
Пример:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
HANDLE hFile=...;//хендл уже открытого файла
 
HANDLE hFile=...;//хендл уже открытого файла
 
DWORD dwdFileLen=...;//размер открытого файла
 
DWORD dwdFileLen=...;//размер открытого файла
Строка 597: Строка 592:
 
===Как в MFC Grid control отобразить картинку в ячейке?===
 
===Как в MFC Grid control отобразить картинку в ячейке?===
 
Нужно создать список изображений (CImageList), затем передать указатель на список в таблицу. Поскольку элемент управления лишь копирует указатель, список должен создаваться динамически, либо быть членом класса, экземпляр которого существует всё время работы таблицы.
 
Нужно создать список изображений (CImageList), затем передать указатель на список в таблицу. Поскольку элемент управления лишь копирует указатель, список должен создаваться динамически, либо быть членом класса, экземпляр которого существует всё время работы таблицы.
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
CImageList m_ImageList;
 
CImageList m_ImageList;
 
CGridCtrL m_Grid1;
 
CGridCtrL m_Grid1;
Строка 606: Строка 601:
 
//...
 
//...
  
//вставляем в контрол
+
//вставляем в элемент управления
 
m_Grid1.SetImageList(&m_ImageList);
 
m_Grid1.SetImageList(&m_ImageList);
  
Строка 614: Строка 609:
 
===Как при помощи IPicture отобразить картинку из файла? ===
 
===Как при помощи IPicture отобразить картинку из файла? ===
 
Пример - несложная функция, отображающая картинку из файла. Поддерживаются форматы BMP, GIF, JPEG, PNG, TIFF, EMF
 
Пример - несложная функция, отображающая картинку из файла. Поддерживаются форматы BMP, GIF, JPEG, PNG, TIFF, EMF
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
#include "atlconv.h"
 
#include "atlconv.h"
 
#define HandleIsValid(H) (H!=(HANDLE)-1 && H!=(HANDLE)0)
 
#define HandleIsValid(H) (H!=(HANDLE)-1 && H!=(HANDLE)0)
Строка 640: Строка 635:
  
 
CString txt=pchzFilePath;
 
CString txt=pchzFilePath;
hr= ::OleLoadPicturePath(
+
hr=::OleLoadPicturePath(
 
const_cast<LPOLESTR>(T2COLE(txt)),
 
const_cast<LPOLESTR>(T2COLE(txt)),
 
0,0,0,IID_IPicture,
 
0,0,0,IID_IPicture,
Строка 658: Строка 653:
 
OLE_YPOS_HIMETRIC cySrc;
 
OLE_YPOS_HIMETRIC cySrc;
  
if(S_OK!=pPic->get_Width(&cxSrc))throw 0;
+
if(S_OK!=pPic->get_Width(&cxSrc))
if(S_OK!=pPic->get_Height(&cySrc))throw 0;
+
{
 +
throw 0;
 +
}
 +
 
 +
if(S_OK!=pPic->get_Height(&cySrc))
 +
{
 +
throw 0;
 +
}
  
 
Wid=cxSrc/26;
 
Wid=cxSrc/26;
Строка 666: Строка 668:
 
//рисуем
 
//рисуем
 
if(S_OK !=pPic->Render(pDestDC->GetSafeHdc(),
 
if(S_OK !=pPic->Render(pDestDC->GetSafeHdc(),
0,Hig,Wid,-Hig,0,0,cxSrc,cySrc,0))throw 0;
+
0,Hig,Wid,-Hig,0,0,cxSrc,cySrc,0))
 +
{
 +
throw 0;
 +
}
 
}
 
}
 
catch(...)
 
catch(...)
Строка 680: Строка 685:
  
  
if(pWid)*pWid=Wid;
+
if(pWid)
if(pHig)*pHig=Hig;
+
{
 +
*pWid=Wid;
 +
}
 +
 
 +
if(pHig)
 +
{
 +
*pHig=Hig;
 +
}
  
 
return result;
 
return result;
Строка 688: Строка 700:
  
 
===Как позволить пользователю начать ввод новой строки в многострочном поле редактирования?===
 
===Как позволить пользователю начать ввод новой строки в многострочном поле редактирования?===
Нужно в редакторе ресурсов поставить для свойств окошка CEdit галочку "WantReturn" или добавить стиль ES_WANTRETURN при создании CEdit контрола динамически. Тогда при нажатии Enter в поле редиктирования будет вводиться новая строка.
+
Нужно в редакторе ресурсов поставить для свойств окошка CEdit галочку "WantReturn" или добавить стиль ES_WANTRETURN при создании CEdit элемента управления динамически. Тогда при нажатии Enter в поле редактирования будет вводиться новая строка.
  
 
===Как выводят картинку-логотип(splash screen) при запуске программы?===
 
===Как выводят картинку-логотип(splash screen) при запуске программы?===
Строка 705: Строка 717:
 
===Как работать с буфером обмена (Clipboard)?===
 
===Как работать с буфером обмена (Clipboard)?===
  
КОПИРОВАНИЕ В БУФЕР ОБМЕНА:
+
====КОПИРОВАНИЕ В БУФЕР ОБМЕНА====
  
Алгоритм
+
Алгоритм:
<syntaxhighlight>
+
# Готовим данные
1.Готовим данные
+
#* Выделяем память из кучи,  вызывая GlobalAlloc()
а. Выделяем память из кучи,  вызывая GlobalAlloc()
+
#* Получаем указатель на выделенную память, вызывая GlobalLock()
б. Получаем указатель на выделенную память, вызывая GlobalLock()
+
#* Заполняем данные
в. Заполняем данные
+
#* Освобождаем указатель, вызывая GlobalUnlock();
г. Освобождаем указатель, вызывая GlobalUnlock();
+
# Открываем буфер обмена, вызывая OpenClipboard();
 
+
# Очищаем буфер, вызывая EmptyClipboard();
2.Открываем буфер обмена, вызывая OpenClipboard();
+
# Вызываем SetClipboardData() один раз для каждого формата вставляемых данных (имеется в виду - если одни и те же данные представлены в разных форматах, и приложение может эти форматы создать)
 
+
# Закрываем буфер, вызывая CloseClipboard();
3.Очищаем буфер, вызывая EmptyClipboard();
+
# ВЫЗЫВАТЬ GlobalFree() НЕ НУЖНО, в этом случае это предоставлено системе
 
+
4.Вызываем SetClipboardData() один раз для каждого формата
+
вставляемых данных (имеется в виду - если одни и те же
+
данные представлены в разных форматах, и приложение
+
может эти форматы создать)
+
 
+
5.Закрываем буфер, вызывая CloseClipboard();
+
 
+
6.ВЫЗЫВАТЬ GlobalFree() НЕ НУЖНО, в этом случае это
+
предоставлено системе
+
</syntaxhighlight>
+
  
 
Скажем, хотим поместить в буфер обмена текст.
 
Скажем, хотим поместить в буфер обмена текст.
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
//готовим данные
+
//готовим данные
//выделяем из кучи память для данных
+
//выделяем из кучи память для данных
HANDLE hglbCopy = GlobalAlloc(GMEM_MOVEABLE,10);
+
HANDLE hglbCopy = GlobalAlloc(GMEM_MOVEABLE,10);
if(!hglbCopy)return;
+
if(!hglbCopy)return;
  
//получаем указатель
+
//получаем указатель
void* lpStr = GlobalLock(hglbCopy);
+
void* lpStr = GlobalLock(hglbCopy);
if(!lpStr)return;
+
if(!lpStr)return;
  
//заполняем данные
+
//заполняем данные
strcpy((char*)lpStr,"my text");
+
strcpy((char*)lpStr,"my text");
  
//освобождаем указатель
+
//освобождаем указатель
GlobalUnlock(hglbCopy);
+
GlobalUnlock(hglbCopy);
lpStr=0;
+
lpStr=0;
  
//открываем буфер обмена
+
//открываем буфер обмена
OpenClipboard();
+
OpenClipboard();
//очищаем
+
//очищаем
EmptyClipboard();
+
EmptyClipboard();
  
//текстовый формат
+
//текстовый формат
SetClipboardData(CF_TEXT,hglbCopy);
+
SetClipboardData(CF_TEXT,hglbCopy);
  
//закрываем буфер
+
//закрываем буфер
CloseClipboard();
+
CloseClipboard();
 
</syntaxhighlight>
 
</syntaxhighlight>
  
---
 
  
ИЗВЛЕЧЕНИЕ ИЗ БУФЕРА ОБМЕНА
 
  
Алгоритм
+
====ИЗВЛЕЧЕНИЕ ИЗ БУФЕРА ОБМЕНА====
<syntaxhighlight>
+
1.Проверяем, что поддерживается нужный формат данных,
+
вызывая IsClipboardFormatAvailable()
+
  
2.Открываем буфер обмена, вызывая OpenClipboard();
+
Алгоритм:
 
+
# Проверяем, что поддерживается нужный формат данных, вызывая IsClipboardFormatAvailable()
3.Достаём данные
+
# Открываем буфер обмена, вызывая OpenClipboard();
а.Получаем из буфера хендл требуемого формата,
+
# Достаём данные
вызывая GetClipboardData()
+
#* Получаем из буфера хендл требуемого формата, вызывая GetClipboardData()
б.Получаем указатель на выделенную память, вызывая GlobalLock()
+
#* Получаем указатель на выделенную память, вызывая GlobalLock()
в.Работаем с данными
+
#* Работаем с данными
г.Освобождаем указатель, вызывая GlobalUnlock();
+
#* Освобождаем указатель, вызывая GlobalUnlock();
 
+
# Закрываем буфер, вызывая CloseClipboard();
4.Закрываем буфер, вызывая CloseClipboard();
+
</syntaxhighlight>
+
  
 
Скажем, хотим извлечь из буфера обмена текст.
 
Скажем, хотим извлечь из буфера обмена текст.
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
//Проверяем, что поддерживается нужный формат данных,
+
//Проверяем, что поддерживается нужный формат данных,
if(!IsClipboardFormatAvailable(CF_TEXT))return;
+
if(!IsClipboardFormatAvailable(CF_TEXT))return;
  
//открываем буфер обмена
+
//открываем буфер обмена
OpenClipboard();
+
OpenClipboard();
  
//достаём данные
+
//достаём данные
  
//текстовый формат
+
//текстовый формат
HANDLE hglbCopy = GetClipboardData(CF_TEXT);
+
HANDLE hglbCopy = GetClipboardData(CF_TEXT);
if(!hglbCopy)return;
+
if(!hglbCopy)return;
  
//получаем указатель
+
//получаем указатель
void* lpStr = GlobalLock(hglbCopy);
+
void* lpStr = GlobalLock(hglbCopy);
if(!lpStr)return;
+
if(!lpStr)return;
  
//читаем данные
+
//читаем данные
char data[10];
+
char data[10];
memmove(data,lpStr,sizeof(data));
+
memmove(data,lpStr,sizeof(data));
  
//освобождаем указатель
+
//освобождаем указатель
GlobalUnlock(hglbCopy);
+
GlobalUnlock(hglbCopy);
lpStr=0;
+
lpStr=0;
  
//закрываем буфер
+
//закрываем буфер
CloseClipboard();
+
CloseClipboard();
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Строка 814: Строка 808:
 
===Как получить полный путь к экзешнику из самой программы?===
 
===Как получить полный путь к экзешнику из самой программы?===
 
Можно прочитать параметры командной строки - в командную строку первым параметром система всегда передаёт заключённый в кавычки полный путь к файлу запущенной программы. Достаём путь следующим образом:
 
Можно прочитать параметры командной строки - в командную строку первым параметром система всегда передаёт заключённый в кавычки полный путь к файлу запущенной программы. Достаём путь следующим образом:
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
BOOL CMyApp::InitInstance()
 
BOOL CMyApp::InitInstance()
 
{
 
{
Строка 837: Строка 831:
 
Один из способов - сделать копию экзешника и из него обновиться
 
Один из способов - сделать копию экзешника и из него обновиться
  
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
#define def_exeNAMEup "c:\\myprog_toupdate.exe" //путь к старому файлу
 
#define def_exeNAMEup "c:\\myprog_toupdate.exe" //путь к старому файлу
#define def_exeNAMEdnld "c:\\myprog_downloaded.exe" //путь к новому файлу (уже "скачали" :) )
+
#define def_exeNAMEdnld "c:\\myprog_downloaded.exe" //путь к новому файлу (уже "скачали":) )
 
#define def_keyUdate "/update"
 
#define def_keyUdate "/update"
  
Строка 882: Строка 876:
 
BOOL CTESTFAQApp::InitInstance()
 
BOOL CTESTFAQApp::InitInstance()
 
{
 
{
 
+
//смотрим, не запущено ли для апдейта?
//смотрим, не запустили ли для апдейта?
+
 
+
 
CString txt;
 
CString txt;
 
txt=m_lpCmdLine;
 
txt=m_lpCmdLine;
Строка 918: Строка 910:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== Как производится конвертация из кодировки UTF8 в 1251 и наоборот ?===
+
=== Как производится конвертация из кодировки UTF8 в 1251 и наоборот?===
  
 
Можно перевести строку из UTF8 в Unicode, затем из Unicode в 1251
 
Можно перевести строку из UTF8 в Unicode, затем из Unicode в 1251
Строка 924: Строка 916:
 
Ниже приведена структура, содержащая процедуры перекодирования,
 
Ниже приведена структура, содержащая процедуры перекодирования,
 
а также процедуру с примером использования
 
а также процедуру с примером использования
<syntaxhighlight>
+
<syntaxhighlight lang="cpp">
 
//описание структуры
 
//описание структуры
 
struct coder
 
struct coder
Строка 936: Строка 928:
 
//тест на возможность преобразования
 
//тест на возможность преобразования
 
res_len=MultiByteToWideChar(CP_UTF8,0,utf8_string,-1,0,0);
 
res_len=MultiByteToWideChar(CP_UTF8,0,utf8_string,-1,0,0);
if(!res_len)return 0;
+
if(!res_len)
 +
{
 +
return 0;
 +
}
  
 
//выделяем память
 
//выделяем память
 
pRes = new wchar_t[res_len];
 
pRes = new wchar_t[res_len];
if(!pRes)return 0;
+
if(!pRes)
 +
{
 +
return 0;
 +
}
  
 
//преобразование
 
//преобразование
Строка 960: Строка 958:
 
//тест на возможность преобразования
 
//тест на возможность преобразования
 
res_len = WideCharToMultiByte(1251,0,unicode_string,-1,0,0,0,0);
 
res_len = WideCharToMultiByte(1251,0,unicode_string,-1,0,0,0,0);
if(!res_len)return 0;
+
if(!res_len)
 +
{
 +
return 0;
 +
}
  
 
//выделяем память
 
//выделяем память
 
pRes=new char[res_len];
 
pRes=new char[res_len];
if(!pRes)return 0;
+
if(!pRes)
 +
{
 +
return 0;
 +
}
  
 
//преобразование
 
//преобразование
Строка 1008: Строка 1012:
 
//cp1251_string - результат
 
//cp1251_string - результат
 
AfxMessageBox(cp1251_string);
 
AfxMessageBox(cp1251_string);
 
  
 
//не забываем удалить массивы
 
//не забываем удалить массивы
Строка 1016: Строка 1019:
 
unicode_string=0;
 
unicode_string=0;
 
}
 
}
 +
 
if(cp1251_string)
 
if(cp1251_string)
 
{
 
{
Строка 1033: Строка 1037:
 
Компоненты  ADO (ADODC,DATAGRID и т.п.) это ActiveX.
 
Компоненты  ADO (ADODC,DATAGRID и т.п.) это ActiveX.
  
В редакторе ресурсов, во всплывающем меню, есть Insert ActiveX Control -> открывается список всех компоент, зарегистрированых на машине. Нужно найти компоненты (Это компоненты от MS и они помечены (OLEDB)) и вставить их в диалог. Для того что бы иметь возможность управлять ими, нужно импортировать обертки для них, это делается при помощи ClassWizard, там есть импорт->класс->указать файл с компоентой (OSX). Появляется список всех классов, объявленых внутри.
+
В редакторе ресурсов, во всплывающем меню, есть Insert ActiveX Control -> открывается список всех компонент, зарегистрированных на машине. Нужно найти компоненты (Это компоненты от MS и они помечены (OLEDB)) и вставить их в диалог. Для того что бы иметь возможность управлять ими, нужно импортировать обертки для них, это делается при помощи ClassWizard, там есть импорт->класс->указать файл с компонентой (OSX). Появляется список всех классов, объявленных внутри.
  
 
Расставляем нужные галочки, нажимаем ОК.
 
Расставляем нужные галочки, нажимаем ОК.
  
 
[[Category:FAQ]]
 
[[Category:FAQ]]

Версия 23:03, 23 октября 2008

Содержание

Как узнать, что пользователь меняет текст в приложении на основе 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. Компилятор выдаёт ошибку. Что надо делать?

Перекрёстное определение обходится следующим образом: код обоих классов разносится в пары файлов *.h и *.cpp, а перед каждым классом вписывается предопределение другого класса:


файл "class1.h"

class Class2;//предопределение Class2
 
Class1
{
	Class2* m_p2;//компилятор разрешит объявление указателя Class2*
 
	void F1(Class2* p);//компилятор разрешит объявление указателя Class2*
	void F2(Class1* p);
};

файл "class1.cpp"

#include "class1.h"
#include "class2.h"
 
void Class1::F1(Class2* p)
{
	...
}
 
void Class1::F2(Class1* p)
{
	...
}


файл "class2.h"

class Class1;//предопределение Class1
 
Class2
{
	Class1* m_p1;//компилятор разрешит объявление указателя Class1*
 
	void F3(Class1* p);//компилятор разрешит объявление указателя Class1*
};


файл "class2.cpp"

#include "class2.h"
#include "class1.h"
 
void Class2::F3(Class1* p)
{
	...
}


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

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

Для этого можно использовать функции

  • GetKeyboardLayout(...); // определить текущую раскладку
  • LoadKeyboardLayout(...); // загрузить новую раскладку
  • VerLanguageName(...); // получить строку с описанием языка

Подробности - в MSDN

Как получить хендл элемента управления, зная его идентификатор?

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

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

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

Для этого нужно послать родительскому окну сообщение WM_CLOSE:

через указатель на родительское окно:

pParent->PostMessage(WM_CLOSE);

при помощи хендла родительского окна:

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

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

  1. для конвертирования BSTR в CString нужно просто присвоить переменной типа CString переменную типа BSTR.

Оператор "=" класса CString сам выполнит всю работу.

  1. для конвертирования BSTR в CString нужно выполнить код:
//указатель на будущий буфер с BSTR.
BSTR bstrHE=0;
//	(По сути, BSTR определён как 
//	typedef WCHAR* BSTR;
//	то есть указатель на 16-битный символ юникод)
 
//строка для конвертации
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++ простейший макрос, где невозможно ошибиться, а компилятор всё же выдаёт ошибку. Не пойму, в чём дело?

Скорее всего после одного из символов соединения строк "\" имеется пробел или табуляция. Их надо удалить. Можно найти их "на ощупь", а можно включить показ непечатных символов в студии. Найти эту команду можно так:

Tools->Customize...->вкладка Commands. В окошке Category выбрать "Edit", и среди кнопок справа найти кнопку, на которой написано "a.b"

Эту кнопку надо перетащить на одну из панелей инструментов студии.

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

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

  • Process32First(...);
  • Precess32Next(...);

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

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

Чтобы добавить или изменить их программно, необходимо воспользоваться ключом реестра

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment

Затем нужно отправить широковещательное сообщение WM_SETTINGCHANGE (это позволит приложениям узнать об изменениях):

::SendMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0);


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

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

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

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

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

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

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

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

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

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

Почему не вызывается OnUpdate для пунктов меню (не получается ни затенить, ни отметку поставить)?

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

Визардом этот обработчик не добавляется, поэтому можно переопределить виртуальную DefWindowProc() и там обработать:

#include <afxpriv.h>	//этот файл надо включить, там определёна WM_KICKIDLE
 
LRESULT CMyDialog::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	if(message==WM_KICKIDLE)
	{
		//делаем апдейт для всех пунктов меню
		CMenu* pMainMenu=GetMenu();
		if(pMainMenu)
		{
			CCmdUI cmdUI;
			for(UINT n=0; n < pMainMenu->GetMenuItemCount(); n++)
			{
				CMenu* pSubMenu = pMainMenu->GetSubMenu(n);
				if(!pSubMenu)continue;
 
				cmdUI.m_nIndexMax = pSubMenu->GetMenuItemCount();
				for(UINT i=0; i<cmdUI.m_nIndexMax; i++)
				{
					cmdUI.m_nIndex = i;
					cmdUI.m_nID = pSubMenu->GetMenuItemID(i);
					cmdUI.m_pMenu = pSubMenu;
					cmdUI.DoUpdate(this, FALSE);
				}
			}
		}
	}
 
	return CDialog::DefWindowProc(message, wParam, lParam);
}


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

При создании окна нужно убрать стиль WS_SYSMENU (теперь пользователь корректно может закрыть окно только Alt+F4, ну или если вы предоставите ему дополнительную возможность сделать это)

Пример 1. (для SDI, MDI)

//этот обработчик уже добавлен визардом
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !CFrameWnd::PreCreateWindow(cs) )
		return FALSE;
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs
 
	///////////////////////////////
	//добавленная часть
	{
		//убираем стиль
		cs.style&=~WS_SYSMENU;
	}
	///////////////////////////////
 
	return TRUE;
}

Пример 2. (для диалога)

Если диалог описан в ресурсах, то в свойствах диалога убрать галочки

  • "System menu"
  • "Minimize box"
  • "Maximize box"

Как запретить пользователю нажать на кнопку?

Нужно применить метод класса CWnd::EnableWindow(...) для кнопки. Значение параметра 0 делает кнопку неактивной, 1 - делает активной (кстати, не только для кнопки можно, а для любого класса, производного от класса CWnd).


Пусть имеется некий диалог, на нём лежит кнопка c ID == IDC_1. В любом месте кода диалога (кроме конструктора и деструктора, хотя, если проверить наличие валидного хендла диалога, как в примере, то ничего страшного не будет и там) выполняем код

//делаем кнопку неактивной
if(m_hWnd)
{
	CWnd* pw=0;
	pw=GetDlgItem(IDC_1);
	if(pw)
	{
		pw->EnableWindow(0);
	}
}

Что означают сообщения, которые студия выводит при компиляции, вроде таких: Loaded 'C:\WINDOWS\SYSTEM\WSOCK32.DLL', no matching symbolic information found.

Это строка говорит о том, что студия не смогла найти отладочные символы для WSOCK32.DLL. В этом нет ничего страшного, просто при наличии отладочных символов в процессе отладки можно получить доступ к именам функции из системных DLL. Например, вместо

KERNEL32! 0x77E8B184()

увидим

KERNEL32!CreateThread.

Как обработать сообщения, которое приходит к некому элементу управления?

Скажем, нужно обработать сообщения, приходящие к элементу класса CEdit. Нужно произвести от CEdit свой класс, и в виртуальной процедуре класса WindowProc перехватить нужные сообщения.

virtual LRESULT WindowProc(
	UINT message,
	WPARAM wParam,
	LPARAM lParam 
);

Пример. Полностью выключаем, скажем, обработку сообщения WM_CHAR

LRESULT CMyEdit::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	switch(message)
	{
		case WM_CHAR:
		{
			return 0;
		}
		break;
	}
 
	return CEdit::WindowProc(message, wParam, lParam);
}

Чтобы связать экземпляр класса с элементом управления на форме, добавьте визардом для элемента управления переменную класса (выбрав не Value а Control).

Как настроить количество пробелов в табуляции?

Есть пара способов:

  1. Tools->Options->Tabs->Insert Spaces
  2. правой кнопкой мыши щёлкнуть по тексту, в контекстном меню выбрать properties

Как автоматически расставить отступы?

Нужно в студии выделить текст для форматирования, нажать Alt+F8.

Ещё есть программа Artistic Style ( http://sourceforge.net/projects/astyle/ ), которая занимается переформатированием кода.

Поиск границ блока

Сочетание клавиш CTRL+ "}" ищет парную фигурную скобку в тексте и переходит к ней.

Вертикальное выделение текста

Если удерживать клавишу Alt, а затем начать выделять текст мышкой, то область выделения принимает форму прямоугольника, что позволяет выделять вертикальные фрагменты текста.

Как узнать количество установленных в CListCtrl столбцов?

Пример

//указатель на переменную-элемент управления
CListCtrl* pL=...;
 
//получаем количество столбцов
int count=pL->GetHeaderCtrl()->GetItemCount();

Как получить иконку приложения?

Если приложение запущено, то нужно найти его главное окно и послать ему сообщение WM_GETICON.

//функция возвращант хендл иконки 
LRESULT SendMessage(hWnd, WM_GETICON, wParam, 0);
 
//hWnd == хендл окна приложения
//wParam == 
//	1)==ICON_BIG - получить большую иконку
//	2)==ICON_SMALL - получить маленькую иконку
//	3)==ICON_SMALL2 - получить маленькую иконку, если она определена
//				в приложении. Если её нет, то маленькую иконку, 
//				сгенерированную системой из большой иконки

Как в CString можно найти или вырезать часть строки?

Это можно сделать при помощи методов класса CString:

//вырезает кусок строки
CString Mid(int nFirst) const;
CString Mid(int nFirst,  int nCount) const;
 
//возвращает кусок строки (сначала или с конца)
CString Left(int nCount ) const;
CString Right(int nCount ) const;
 
//возвращает начальный кусок строки, в котором есть только
//символы из набора, представленного в lpszCharSet
CString SpanIncluding(LPCTSTR lpszCharSet ) const;
 
//возвращает начальный кусок строки, в котором нет
//символов из набора, представленного в lpszCharSet
CString SpanExcluding(LPCTSTR lpszCharSet ) const; 
 
//убирает "пробелоподобные" символы из самого начала строки
//(то есть - пробел, табуляцию (\t), возврат каретки, перевод строки (/r/n))
void TrimLeft();
//убирает все повторы символа из самого начала строки
void TrimLeft(TCHAR chTarget );
//убирает из самого начала строки все символа из набора lpszTargets 
void TrimLeft(LPCTSTR lpszTargets );
 
void TrimRight();
void TrimRight(TCHAR chTarget );
void TrimRight(LPCTSTR lpszTargets );
 
//поиск в строке
int Find( TCHAR ch ) const;
int Find( LPCTSTR lpszSub ) const;
int Find( TCHAR ch, int nStart ) const;
int Find( LPCTSTR pstr, int nStart ) const;
 
//поиск, начиная с конца
int ReverseFind( TCHAR ch ) const;
 
//поиск позиции первого символа, одного из набора,
// представленного в lpszCharSet
int FindOneOf( LPCTSTR lpszCharSet ) const;

Как отобразить на элементах управления промежуточные результаты длительных вычислений?

В общем случае это делается принудительной перерисовкой нужного окна путём объявления этого окна невалидным

pWnd->Invalidate(0);

а затем непосредственной отсылки в оконную процедуру сообщения WM_PAINT

pWnd->UpdateWindow();

Пример:

CWnd* pWnd=...;//окно, которое надо перерисовывать
 
for(int i=0; i<10000; i++)
{
	//меняется содержимое окна
	//...
 
	//немедленная перерисовка
	pWnd->Invalidate(0);
	pWnd->UpdateWindow();
}

Также можно также просто вызвать метод RedrawWindow() с параметрами по умолчанию.

Я написал DLL, которую используют несколько приложений. Всё вроде работает, но когда происходит очередной вызов функции из DLL, почему то данные в функции обнуляются. С чем это связано?

Переменные и массивы в DLL, содержимое которых должно использоваться несколькими процессами, должны объявляться статическими. Статическая переменная или массив инициализируются только один раз в момент загрузки DLL. Пример:

DWORD calltest()
{
	//будет выполнено только при первом вызове
	static DWORD callcount=0;
	static DWORD str[1000]={0}; 
 
	//будет выполняться каждый раз
	callcount++;
	return callcount;
}

Как открыть проекцию файла в память и как с ней работать?

Создание проекции:

HANDLE CreateFileMapping(
	HANDLE hFile,	//хендл уже открытого файла
	LPSECURITY_ATTRIBUTES lpAttributes,
	DWORD flProtect,	//способ открытия проекции
	DWORD dwMaximumSizeHigh,	//размер файла (старшие 4 байта, обычно==0)
	DWORD dwMaximumSizeLow,	//размер файла (младшие 4 байта)
	LPCTSTR lpName
);

Доступ к созданной проекции производится процедурой:

LPVOID MapViewOfFile(
	HANDLE hFileMappingObject, //хендл проекции
	DWORD dwDesiredAccess,	//способ работы с проекцией
	DWORD dwFileOffsetHigh,
	DWORD dwFileOffsetLow, //смещение от начала файла (младшие 4 байта)
	SIZE_T dwNumberOfBytesToMap //длина в байтах (если ==0 - то весь файл)
);

далее с файлом можно работать как с обычным массивом в памяти.

После работы с проекцией, её надо освободить процедурой

BOOL UnmapViewOfFile(
	LPCVOID lpBaseAddress //адрес, который вернула процедура MapViewOfFile
);

Пример:

HANDLE hFile=...;//хендл уже открытого файла
DWORD dwdFileLen=...;//размер открытого файла
 
HANDLE hMapFile=0;//хендл для проекции
 
//создаём проекцию "только для чтения"
hMapFile=::CreateFileMapping(hFile,0,PAGE_READONLY,0,dwdFileLen,0);
 
//хендл hFile можно закрыть уже здесь, в принципе,
//но мы сделаем это позже
 
//получаем доступ к проекции (тоже только для чтения)
BYTE* pbyFile=(BYTE*)::MapViewOfFile(hMapFile,FILE_MAP_READ,0,0,0);
 
///////////////////
//тут работаем с массивом pbyFile[dwdFileLen] как с обычным,
//только не забываем, что он открыт только для чтения
//...
//...
//...
///////////////////
 
//отключаем файл данных от адресного пространства
UnmapViewOfFile(pbyFile);
 
//освобождаем хендл проекции
CloseHandle(hMapFile)
 
//освобождаем хендл открытого файла
CloseHandle(hFile);

Как в MFC Grid control отобразить картинку в ячейке?

Нужно создать список изображений (CImageList), затем передать указатель на список в таблицу. Поскольку элемент управления лишь копирует указатель, список должен создаваться динамически, либо быть членом класса, экземпляр которого существует всё время работы таблицы.

CImageList m_ImageList;
CGridCtrL m_Grid1;
...
...
//неким образом создаётся список
m_ImageList.Create(...);
//...
 
//вставляем в элемент управления
m_Grid1.SetImageList(&m_ImageList);
 
//

Как при помощи IPicture отобразить картинку из файла?

Пример - несложная функция, отображающая картинку из файла. Поддерживаются форматы BMP, GIF, JPEG, PNG, TIFF, EMF

#include "atlconv.h"
#define HandleIsValid(H) (H!=(HANDLE)-1 && H!=(HANDLE)0)
 
//*pDestDC - CDC, на который предполагается вывод картинки
//pchzFilePath - путь к файлу
//pWid - (возвращает) ширина картинки
//pHig - (возвращает) высота картинки
bool DrawBitmapFromFile(CDC* pDestDC,const char* pchzFilePath,int *pWid=0,int *pHig=0)
{
	bool result=false;
 
	if(pWid)*pWid=0;
	if(pHig)*pHig=0;
 
	int Wid=0;
	int Hig=0;
 
	IPicture* pPic=0;
	try
	{
		IPicture* ptmpPic=0;
		USES_CONVERSION;
		HRESULT hr;
 
		CString txt=pchzFilePath;
		hr=::OleLoadPicturePath(
			const_cast<LPOLESTR>(T2COLE(txt)),
			0,0,0,IID_IPicture,
			reinterpret_cast<void **>(&ptmpPic)
			);
 
		if(hr==S_OK && ptmpPic)
		{
			pPic=ptmpPic;
		}
		else
		{
			throw 0;
		}
 
		OLE_XPOS_HIMETRIC cxSrc;
		OLE_YPOS_HIMETRIC cySrc;
 
		if(S_OK!=pPic->get_Width(&cxSrc))
		{
			throw 0;
		}
 
		if(S_OK!=pPic->get_Height(&cySrc))
		{
			throw 0;
		}
 
		Wid=cxSrc/26;
		Hig=cySrc/26;
 
		//рисуем
		if(S_OK !=pPic->Render(pDestDC->GetSafeHdc(),
			0,Hig,Wid,-Hig,0,0,cxSrc,cySrc,0))
		{
			throw 0;
		}
	}
	catch(...)
	{
		result=false;
	}
 
	if(pPic)
	{
		pPic->Release();
		pPic=0;
	}
 
 
	if(pWid)
	{
		*pWid=Wid;
	}
 
	if(pHig)
	{
		*pHig=Hig;
	}
 
	return result;
}

Как позволить пользователю начать ввод новой строки в многострочном поле редактирования?

Нужно в редакторе ресурсов поставить для свойств окошка CEdit галочку "WantReturn" или добавить стиль ES_WANTRETURN при создании CEdit элемента управления динамически. Тогда при нажатии Enter в поле редактирования будет вводиться новая строка.

Как выводят картинку-логотип(splash screen) при запуске программы?

Для этого используется класс, производный от CDialog. Этот диалог после создания показывает себя на экран, выводя на себя рисунок. Также запускает таймер, по срабатывани которого диалог гасится. Создаётся диалог в процедуре InitInstance приложения.

В VC6++ также есть уже готовый компонент

Project->Add To Project -> Components and Controls->(в папке "Visual C++ Components" есть SplashScreen.)

Как сделать, чтобы при выпадении списка у ComboBox была не одна строка, а больше, вроде все свойства покрутил, не помогает Вместо выпадающего списка одна строка и скролл...

В редакторе ресурсов надо щелкнуть в комбобоксе на треугольнике - появляется рамка для растягивания вниз - размер выпадающего списка.

В VC++.net, что делать после того, как на форму установил ActiveX ListView, как объявить класс и переменную для этого элемента?

Щёлкнуть правой кнопкой мыши на элементе, в меню - add variable или add class

Как работать с буфером обмена (Clipboard)?

КОПИРОВАНИЕ В БУФЕР ОБМЕНА

Алгоритм:

  1. Готовим данные
    • Выделяем память из кучи, вызывая GlobalAlloc()
    • Получаем указатель на выделенную память, вызывая GlobalLock()
    • Заполняем данные
    • Освобождаем указатель, вызывая GlobalUnlock();
  2. Открываем буфер обмена, вызывая OpenClipboard();
  3. Очищаем буфер, вызывая EmptyClipboard();
  4. Вызываем SetClipboardData() один раз для каждого формата вставляемых данных (имеется в виду - если одни и те же данные представлены в разных форматах, и приложение может эти форматы создать)
  5. Закрываем буфер, вызывая CloseClipboard();
  6. ВЫЗЫВАТЬ GlobalFree() НЕ НУЖНО, в этом случае это предоставлено системе

Скажем, хотим поместить в буфер обмена текст.

//готовим данные
//выделяем из кучи память для данных
HANDLE hglbCopy = GlobalAlloc(GMEM_MOVEABLE,10);
if(!hglbCopy)return;
 
//получаем указатель
void* lpStr = GlobalLock(hglbCopy);
if(!lpStr)return;
 
//заполняем данные
strcpy((char*)lpStr,"my text");
 
//освобождаем указатель
GlobalUnlock(hglbCopy);
lpStr=0;
 
//открываем буфер обмена
OpenClipboard();
//очищаем
EmptyClipboard();
 
//текстовый формат
SetClipboardData(CF_TEXT,hglbCopy);
 
//закрываем буфер
CloseClipboard();


ИЗВЛЕЧЕНИЕ ИЗ БУФЕРА ОБМЕНА

Алгоритм:

  1. Проверяем, что поддерживается нужный формат данных, вызывая IsClipboardFormatAvailable()
  2. Открываем буфер обмена, вызывая OpenClipboard();
  3. Достаём данные
    • Получаем из буфера хендл требуемого формата, вызывая GetClipboardData()
    • Получаем указатель на выделенную память, вызывая GlobalLock()
    • Работаем с данными
    • Освобождаем указатель, вызывая GlobalUnlock();
  4. Закрываем буфер, вызывая CloseClipboard();

Скажем, хотим извлечь из буфера обмена текст.

//Проверяем, что поддерживается нужный формат данных,
if(!IsClipboardFormatAvailable(CF_TEXT))return;
 
//открываем буфер обмена
OpenClipboard();
 
//достаём данные
 
//текстовый формат
HANDLE hglbCopy = GetClipboardData(CF_TEXT);
if(!hglbCopy)return;
 
//получаем указатель
void* lpStr = GlobalLock(hglbCopy);
if(!lpStr)return;
 
//читаем данные
char data[10];
memmove(data,lpStr,sizeof(data));
 
//освобождаем указатель
GlobalUnlock(hglbCopy);
lpStr=0;
 
//закрываем буфер
CloseClipboard();


Как получить полный путь к экзешнику из самой программы?

Можно прочитать параметры командной строки - в командную строку первым параметром система всегда передаёт заключённый в кавычки полный путь к файлу запущенной программы. Достаём путь следующим образом:

BOOL CMyApp::InitInstance()
{
	//добыча полного имени экзешника
	CString csFullExeName;
	{
		CString csAppName=GetCommandLine();
		csAppName.Delete(0,1);
		csAppName.Replace('\"','\0');
		csFullExeName=(const char*)csAppName;
	}
	//теперь csFullExeName содержит искомый путь
 
	//...
	//...
}

Каким способом exe файл может заменить самого себя?

К примеру, программа должна обновляется через Internet и хочет обновить свой exe-файл. Но так как он в данный момент запущен, это будет, естественно, невозможно сделать напрямую. Один из способов - сделать копию экзешника и из него обновиться

#define def_exeNAMEup	"c:\\myprog_toupdate.exe"		//путь к старому файлу
#define def_exeNAMEdnld	"c:\\myprog_downloaded.exe"		//путь к новому файлу (уже "скачали":) )
#define def_keyUdate	"/update"
 
void CTESTFAQApp::UpdateItself()
{
	//добыча полного имени экзешника
	CString csFullExeName;
	{
		CString csAppName=GetCommandLine();
		csAppName.Delete(0,1);
		csAppName.Replace('\"','\0');
		csFullExeName=(const char*)csAppName;
	}
	//теперь csFullExeName - содержит искомый путь
 
	//делаем копию экзешника с другим именем
	CopyFile(csFullExeName,def_exeNAMEup,0);
 
	//передаём в параметры нового процесса ключ и путь к текущему файлу
	CString csParams=def_keyUdate;
	csParams+=" ";
	csParams+=csFullExeName;
 
	//запускаем копию
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	ZeroMemory(&si,sizeof(si));
	si.cb = sizeof(si);
	ZeroMemory(&pi,sizeof(pi));
	if(CreateProcess(def_exeNAMEup,def_keyUdate,0,0,0,0,0,0,&si,&pi))
	{
		//завершаем текущий процесс
		ExitFromMyApp();
	}
}
 
void CTESTFAQApp::ExitFromMyApp()
{
	exit(0);
}
 
BOOL CTESTFAQApp::InitInstance()
{
	//смотрим, не запущено ли для апдейта?
	CString txt;
	txt=m_lpCmdLine;
	if(txt.Find(def_keyUdate)==0)
	{
		//делаем айдейт
		txt.Replace(def_keyUdate,"");
		txt.TrimLeft();
 
		CString csFullExeName=txt;
 
		//берём откуда то уже скачанный файл обновления
		//...
		CString csFull_Downloaded_ExeName=def_exeNAMEdnld;
 
		//копируем файл (обновляем старый то есть)
		CopyFile(csFull_Downloaded_ExeName,csFullExeName,0);
 
		//запускаем обновлённого мученника
		STARTUPINFO si;
		PROCESS_INFORMATION pi;
		ZeroMemory(&si,sizeof(si));
		si.cb = sizeof(si);
		ZeroMemory(&pi,sizeof(pi));
		if(CreateProcess(csFullExeName,0,0,0,0,0,0,0,&si,&pi))
 
		ExitFromMyApp();
 
	}
	//...
	//...
}

Как производится конвертация из кодировки UTF8 в 1251 и наоборот?

Можно перевести строку из UTF8 в Unicode, затем из Unicode в 1251

Ниже приведена структура, содержащая процедуры перекодирования, а также процедуру с примером использования

//описание структуры
struct coder
{
	//utf8->unicode
	static wchar_t* utf8_to_unicode__dontForgetDeleteArr(const char *utf8_string)
	{
		wchar_t* pRes=0;
		int res_len=0;
 
		//тест на возможность преобразования
		res_len=MultiByteToWideChar(CP_UTF8,0,utf8_string,-1,0,0);
		if(!res_len)
		{
			return 0;
		}
 
		//выделяем память
		pRes = new wchar_t[res_len];
		if(!pRes)
		{
			return 0;
		}
 
		//преобразование
		if(!MultiByteToWideChar(CP_UTF8,0,utf8_string,-1,pRes,res_len))
		{
			delete [] pRes;
			return 0;
		}
 
		return pRes;
	}
 
	//unicode->1251
	static char * unicode_to_1251__dontForgetDeleteArr(const wchar_t *unicode_string)
	{
		char* pRes=0;
		int res_len=0;
 
		//тест на возможность преобразования
		res_len = WideCharToMultiByte(1251,0,unicode_string,-1,0,0,0,0);
		if(!res_len)
		{
			return 0;
		}
 
		//выделяем память
		pRes=new char[res_len];
		if(!pRes)
		{
			return 0;
		}
 
		//преобразование
		if(!WideCharToMultiByte(1251,0,unicode_string,-1,pRes,res_len,0,0))
		{
			delete [] pRes;
			return 0;
		}
 
		return pRes;
	}
 
	//процедура с примером
	static void Example()
	{
		wchar_t* unicode_string=0;
		char* cp1251_string=0;
 
		//исходный текст
		char utf8_string[] = "UTF-8 + русский текст";
 
		for(;;)
		{
 
			unicode_string=utf8_to_unicode__dontForgetDeleteArr(utf8_string);
			if(!unicode_string)
			{
				AfxMessageBox("Не удалось конвертировать в unicode!");
				break;
			}
 
			cp1251_string = unicode_to_1251__dontForgetDeleteArr(unicode_string);
 
			if(!cp1251_string)
			{
				AfxMessageBox("Не удалось конвертировать из unicode!");
				break;
			}
 
			break;
		}
 
		//cp1251_string - результат
		AfxMessageBox(cp1251_string);
 
		//не забываем удалить массивы
		if(unicode_string)
		{
			delete [] unicode_string;
			unicode_string=0;
		}
 
		if(cp1251_string)
		{
			delete [] cp1251_string;
			cp1251_string=0;
		}
	}
};
 
//вызов примера
coder::Example();

Как работать с базой данных Access из программы на VC.net?

Проще всего подключить ADO компоненты и сделать все на них.

Компоненты ADO (ADODC,DATAGRID и т.п.) это ActiveX.

В редакторе ресурсов, во всплывающем меню, есть Insert ActiveX Control -> открывается список всех компонент, зарегистрированных на машине. Нужно найти компоненты (Это компоненты от MS и они помечены (OLEDB)) и вставить их в диалог. Для того что бы иметь возможность управлять ими, нужно импортировать обертки для них, это делается при помощи ClassWizard, там есть импорт->класс->указать файл с компонентой (OSX). Появляется список всех классов, объявленных внутри.

Расставляем нужные галочки, нажимаем ОК.