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

Материал из Весельчак У
Перейти к: навигация, поиск
(Перенаправление на FAQ:WinAPI VCPP)
 
(не показана одна промежуточная версия этого же участника)
Строка 1: Строка 1:
−
===Что означают сообщения, которые студия выводит при компиляции, вроде таких: Loaded 'C:\WINDOWS\SYSTEM\WSOCK32.DLL', no matching symbolic information found?===
+
#REDIRECT [[FAQ:WinAPI_VCPP]]
−
 
+
−
Это строка говорит о том, что студия не смогла найти отладочные символы для 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]]
+

Текущая версия на 19:43, 3 октября 2009

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