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

Материал из Весельчак У
Перейти к: навигация, поиск
(Содержимое страницы заменено на «Перенесено сюда: FAQ VC++ Category:FAQ»)
Строка 1: Строка 1:
===Что означают сообщения, которые студия выводит при компиляции, вроде таких: Loaded 'C:\WINDOWS\SYSTEM\WSOCK32.DLL', no matching symbolic information found?===
+
Перенесено сюда: [[FAQ:WinAPI_VCPP|FAQ VC++]]
 
+
Это строка говорит о том, что студия не смогла найти отладочные символы для WSOCK32.DLL. В этом нет ничего страшного. Просто, при наличии отладочных символов в процессе отладки, можно получить доступ к именам функции из системных DLL. Например, вместо ''KERNEL32! 0x77E8B184()'' увидим ''KERNEL32!CreateThread''.
+
 
+
===Как обработать сообщения, которые приходят к элементу управления?===
+
 
+
Скажем, нужно обработать сообщения, приходящие к элементу класса CEdit. Нужно произвести от CEdit свой класс и в виртуальной процедуре класса WindowProc перехватить нужные сообщения.
+
 
+
<syntaxhighlight lang="cpp">
+
virtual LRESULT WindowProc(
+
UINT message,
+
WPARAM wParam,
+
LPARAM lParam
+
);
+
</syntaxhighlight>
+
 
+
Пример. Полностью выключаем, скажем, обработку сообщения WM_CHAR.
+
 
+
<syntaxhighlight lang="cpp">
+
LRESULT CMyEdit::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
+
{
+
switch (message)
+
{
+
case WM_CHAR:
+
{
+
return 0;
+
}
+
break;
+
}
+
+
return CEdit::WindowProc(message, wParam, lParam);
+
}
+
</syntaxhighlight>
+
 
+
Чтобы связать экземпляр класса с элементом управления на форме, добавьте визардом для
+
элемента управления переменную класса (выбрав не Value, а Control).
+
 
+
===Как настроить количество пробелов в табуляции?===
+
 
+
Есть пара способов:
+
# Tools->Options->Tabs->Insert Spaces
+
# Правой кнопкой мыши щёлкнуть по тексту, в контекстном меню выбрать properties.
+
 
+
===Как автоматически расставить отступы?===
+
 
+
Нужно в студии выделить текст для форматирования и нажать Alt+F8.
+
 
+
Ещё есть программа Artistic Style ( http://sourceforge.net/projects/astyle/ ), которая занимается переформатированием кода.
+
 
+
===Поиск границ блока.===
+
 
+
Сочетание клавиш CTRL+"}" ищет парную фигурную скобку в тексте и переходит к ней.
+
 
+
===Вертикальное выделение текста.===
+
 
+
Если удерживать клавишу Alt, а затем начать выделять текст мышкой, то область выделения принимает форму прямоугольника, что позволяет выделять вертикальные фрагменты текста.
+
 
+
===Как узнать количество установленных в CListCtrl столбцов?===
+
 
+
Пример:
+
<syntaxhighlight lang="cpp">
+
// указатель на переменную-элемент управления
+
CListCtrl* pL = ...;
+
 
+
// получаем количество столбцов
+
int count = pL->GetHeaderCtrl()->GetItemCount();
+
</syntaxhighlight>
+
 
+
===Как получить иконку приложения?===
+
 
+
Если приложение запущено, то нужно найти его главное окно и послать ему сообщение WM_GETICON.
+
 
+
<syntaxhighlight lang="cpp">
+
// функция возвращант хендл иконки
+
LRESULT SendMessage(hWnd, WM_GETICON, wParam, 0);
+
 
+
// hWnd == хендл окна приложения
+
// wParam ==
+
// 1)==ICON_BIG - получить большую иконку
+
// 2)==ICON_SMALL - получить маленькую иконку
+
// 3)==ICON_SMALL2 - получить маленькую иконку, если она определена
+
// в приложении. Если её нет, то маленькую иконку,
+
// сгенерированную системой из большой иконки
+
</syntaxhighlight>
+
 
+
===Как в CString можно найти или вырезать часть строки?===
+
 
+
Это можно сделать при помощи методов класса CString:
+
 
+
<syntaxhighlight lang="cpp">
+
// вырезает кусок строки
+
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;
+
</syntaxhighlight>
+
 
+
===Как отобразить на элементах управления промежуточные результаты длительных вычислений?===
+
 
+
В общем случае это делается принудительной перерисовкой нужного окна путём объявления этого окна невалидным.
+
 
+
<syntaxhighlight lang="cpp">
+
pWnd->Invalidate(0);
+
</syntaxhighlight>
+
 
+
Затем непосредственной отсылки в оконную процедуру сообщения WM_PAINT.
+
 
+
<syntaxhighlight lang="cpp">
+
pWnd->UpdateWindow();
+
</syntaxhighlight>
+
 
+
Пример:
+
<syntaxhighlight lang="cpp">
+
CWnd* pWnd = ...; // окно, которое надо перерисовывать
+
 
+
for (int i = 0; i < 10000; i++)
+
{
+
// меняется содержимое окна
+
// ...
+
 
+
// немедленная перерисовка
+
pWnd->Invalidate(0);
+
pWnd->UpdateWindow();
+
}
+
</syntaxhighlight>
+
 
+
Также можно также просто вызвать метод RedrawWindow() с параметрами по умолчанию.
+
 
+
===Я написал DLL, которую используют несколько приложений. Всё работает, но когда происходит очередной вызов функции из DLL, почему то, данные в функции обнуляются. С чем это связано?===
+
 
+
Переменные и массивы в DLL, содержимое которых должно использоваться несколькими процессами, должны объявляться статическими. Статическая переменная или массив инициализируются только один раз в момент загрузки DLL.
+
 
+
Пример:
+
 
+
<syntaxhighlight lang="cpp">
+
DWORD calltest()
+
{
+
// будет выполнено только при первом вызове
+
static DWORD callcount = 0;
+
static DWORD str[1000] = {0};
+
 
+
// будет выполняться каждый раз
+
callcount++;
+
return callcount;
+
}
+
</syntaxhighlight>
+
 
+
===Как открыть проекцию файла в память и как с ней работать?===
+
 
+
Создание проекции:
+
 
+
<syntaxhighlight lang="cpp">
+
HANDLE CreateFileMapping(
+
HANDLE hFile, // хендл уже открытого файла
+
LPSECURITY_ATTRIBUTES lpAttributes,
+
DWORD flProtect, // способ открытия проекции
+
DWORD dwMaximumSizeHigh, // размер файла (старшие 4 байта, обычно - 0)
+
DWORD dwMaximumSizeLow, // размер файла (младшие 4 байта)
+
LPCTSTR lpName
+
);
+
</syntaxhighlight>
+
 
+
Доступ к созданной проекции производится процедурой:
+
 
+
<syntaxhighlight lang="cpp">
+
LPVOID MapViewOfFile(
+
HANDLE hFileMappingObject, // хендл проекции
+
DWORD dwDesiredAccess, // способ работы с проекцией
+
DWORD dwFileOffsetHigh,
+
DWORD dwFileOffsetLow, // смещение от начала файла (младшие 4 байта)
+
SIZE_T dwNumberOfBytesToMap // длина в байтах (если 0 - то весь файл)
+
);
+
</syntaxhighlight>
+
 
+
Далее с файлом можно работать как с обычным массивом в памяти.
+
 
+
После работы с проекцией, её надо освободить.
+
 
+
<syntaxhighlight lang="cpp">
+
BOOL UnmapViewOfFile(
+
LPCVOID lpBaseAddress // адрес, который вернула процедура MapViewOfFile
+
);
+
</syntaxhighlight>
+
 
+
Пример:
+
 
+
<syntaxhighlight lang="cpp">
+
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);
+
</syntaxhighlight>
+
 
+
===Как в MFC Grid control отобразить картинку в ячейке?===
+
 
+
Нужно создать список изображений (CImageList), затем передать указатель на список в таблицу. Поскольку элемент управления лишь копирует указатель, список должен создаваться динамически, либо быть членом класса, экземпляр которого существует всё время работы таблицы.
+
 
+
<syntaxhighlight lang="cpp">
+
CImageList m_ImageList;
+
CGridCtrL m_Grid1;
+
 
+
// ...
+
 
+
// неким образом создаётся список
+
m_ImageList.Create(...);
+
 
+
// ...
+
 
+
//вставляем в элемент управления
+
m_Grid1.SetImageList(&m_ImageList);
+
</syntaxhighlight>
+
 
+
===Как при помощи IPicture отобразить картинку из файла? ===
+
 
+
Пример - несложная функция, отображающая картинку из файла. Поддерживаются форматы BMP, GIF, JPEG, PNG, TIFF, EMF.
+
 
+
<syntaxhighlight lang="cpp">
+
#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;
+
}
+
</syntaxhighlight>
+
 
+
===Как позволить пользователю начать ввод новой строки в многострочном поле редактирования?===
+
 
+
Нужно в редакторе ресурсов поставить для свойств окошка 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)?===
+
 
+
'''Копирование в буфер обмена.'''
+
 
+
Алгоритм:
+
# Готовим данные
+
#* Выделяем память из кучи,  вызывая GlobalAlloc()
+
#* Получаем указатель на выделенную память, вызывая GlobalLock()
+
#* Заполняем данные
+
#* Освобождаем указатель, вызывая GlobalUnlock();
+
# Открываем буфер обмена, вызывая OpenClipboard();
+
# Очищаем буфер, вызывая EmptyClipboard();
+
# Вызываем SetClipboardData() один раз для каждого формата вставляемых данных (имеется в виду - если одни и те же данные представлены в разных форматах, и приложение может эти форматы создать)
+
# Закрываем буфер, вызывая CloseClipboard();
+
# ВЫЗЫВАТЬ GlobalFree() НЕ НУЖНО, в этом случае это предоставлено системе
+
 
+
Скажем, хотим поместить в буфер обмена текст.
+
<syntaxhighlight lang="cpp">
+
// готовим данные
+
// выделяем из кучи память для данных
+
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();
+
</syntaxhighlight>
+
 
+
'''Извлечение из буфера обмена.'''
+
 
+
Алгоритм:
+
# Проверяем, что поддерживается нужный формат данных, вызывая IsClipboardFormatAvailable()
+
# Открываем буфер обмена, вызывая OpenClipboard();
+
# Достаём данные
+
#* Получаем из буфера хендл требуемого формата, вызывая GetClipboardData()
+
#* Получаем указатель на выделенную память, вызывая GlobalLock()
+
#* Работаем с данными
+
#* Освобождаем указатель, вызывая GlobalUnlock();
+
# Закрываем буфер, вызывая CloseClipboard();
+
 
+
Скажем, хотим извлечь из буфера обмена текст.
+
<syntaxhighlight lang="cpp">
+
// Проверяем, что поддерживается нужный формат данных,
+
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();
+
</syntaxhighlight>
+
 
+
===Как получить полный путь к экзешнику из самой программы?===
+
Можно прочитать параметры командной строки - в командную строку первым параметром система всегда передаёт заключённый в кавычки полный путь к файлу запущенной программы. Достаём путь следующим образом:
+
 
+
<syntaxhighlight lang="cpp">
+
BOOL CMyApp::InitInstance()
+
{
+
// добыча полного имени экзешника
+
CString csFullExeName;
+
{
+
CString csAppName = GetCommandLine();
+
csAppName.Delete(0, 1);
+
csAppName.Replace('\"', '\0');
+
csFullExeName = (const char*)csAppName;
+
}
+
// теперь csFullExeName содержит искомый путь
+
 
+
//...
+
//...
+
}
+
</syntaxhighlight>
+
 
+
===Каким способом exe файл может заменить самого себя? ===
+
 
+
К примеру, программа должна обновляется через Internet и хочет обновить свой exe-файл. Но так как он в данный момент запущен, это будет, естественно, невозможно сделать напрямую.
+
Один из способов - сделать копию экзешника и из него обновиться
+
 
+
<syntaxhighlight lang="cpp">
+
// путь к старому файлу
+
#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();
+
}
+
 
+
// ...
+
// ...
+
}
+
</syntaxhighlight>
+
 
+
=== Как производится конвертация из кодировки UTF8 в 1251 и наоборот?===
+
 
+
Можно перевести строку из UTF8 в Unicode, затем из Unicode в 1251
+
 
+
Ниже приведена структура, содержащая процедуры перекодирования, а также процедуру с примером использования.
+
 
+
<syntaxhighlight lang="cpp">
+
// описание структуры
+
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();
+
</syntaxhighlight>
+
 
+
===Как работать с базой данных Access из программы на VC.net?===
+
Проще всего подключить ADO компоненты и сделать все на них.
+
 
+
Компоненты  ADO (ADODC,DATAGRID и т.п.) это ActiveX.
+
 
+
В редакторе ресурсов, во всплывающем меню, есть Insert ActiveX Control -> открывается список всех компонент, зарегистрированных на машине. Нужно найти компоненты (Это компоненты от MS и они помечены (OLEDB)) и вставить их в диалог. Для того что бы иметь возможность управлять ими, нужно импортировать обертки для них, это делается при помощи ClassWizard, там есть импорт->класс->указать файл с компонентой (OSX). Появляется список всех классов, объявленных внутри.
+
 
+
Расставляем нужные галочки, нажимаем ОК.
+
 
+
 
[[Category:FAQ]]
 
[[Category:FAQ]]

Версия 16:06, 3 октября 2009

Перенесено сюда: FAQ VC++