Программирование на Visual C++. Архив рассылки - Алекс Jenter
Шрифт:
Интервал:
Закладка:
В статье из KB сказано, что в том же меню "View" – "Resource Includes" можно указать измененные маршруты заголовочных файлов, например, #include "l.rus/afxprint.rc" вместо #include "afxprint.rc". Вероятно, если это сделать, отпадет необходимость в указании маршрута каталога с русифицированными ресурсами на вкладке "Resources" свойств проекта. Кроме того, в той же статье рекомендуется с помощью редактора ресурсов удалить из раздела "String Table" все неспецифичные для конкретного приложения строки, сгенерериванные AppWizard. Полагаю, это можно не делать. В крайнем случае, на необходимость такой операции укажет компилятор.
Таким образом, нужно один раз перевести на русский язык содержимое нескольких файлов ресурсов, а затем лишь указывать в проектах нужный язык и маршрут каталога с русифицированными файлами.
Андрей ШуклинБольшое спасибо, Андрей.
Это все на сегодня. Пока!
Алекс Jenter [email protected] Красноярск, 2001. Рассылка является частью проекта RSDN.Программирование на Visual C++
Выпуск №46 от 27 мая 2001 г.
Приветствую вас, уважаемые подписчики!
Мой коллега Александр Шаргин решил присоединиться к дисскуссии по поводу свойств в C++:
ОБРАТНАЯ СВЯЗЬСвойства "в стиле VB" невозможно заменить перегрузкой оператора присваивания и приведения типа. Если в классе содержится 10 свойств типа int, мы неизбежно заходим в тупик. Что касается полезности этой концепции, она признана многими разработчиками компонентно-ориентированных средств разработки (кроме VB есть Delphi и BCB, в которые свойства вводились отнюдь не только для поддержки COM, свойства есть в новом языке C# от Микрософт и т. д.). Конечно, свойства – не революция. Вместо них можно использовать пару методов Set/Get. Но они делают смысл происходящего в программе понятнее:
wnd.style |= WS_VISIBLE;
вместо
wnd.SetStyle(wnd.GetStyle() | WS_VISIBLE);
Кроме того, они развивают концепцию сокрытия деталей реализации от пользователя класса: для него свойство выглядит как обычная переменная-член, и он даже не догадывается, что для её реализации используются функции. Не секрет, что многие программисты не любят методы Set/Get и продолжают использовать открытые члены, несмотря на все призывы Страуструпа и иже с ним. Даже в книгах по программированию этот "неправильный" подход встречается сплошь и рядом. Свойства позволяют найти компромисс между этим чисто человеческим нежеланием и важными принципами ООП. В выигрыше оказываются все.
Что касается реализации свойств с C++, здесь перед нами встают проблемы. Если вопрос портирования прграммы для нас не актуален, и мы ограничиваемся VC, я не вижу смысла игнорировать его расширенные возможности. Использование deсlspec(property) в этом случае является исключительно делом вкуса программиста. Принципиальных возражений против его использования нет.
А вот "самодельные" свойства приносят в жертву эффективность программы, и поэтому мы должны или отказаться от них, или улучшить, убрав лишние затраты. Вот пример возможного улучшения.
#include <stddef.h>
//***************************
// Макрос для свойства
#define PROPERTY(ownertype, proptype, prop, getfunc, setfunc)
class class __property##prop
{
public:
operator proptype()
{
return ((ownertype*)((char*)this - offsetof(ownertype, prop)))->getfunc();
}
void operator=(proptype data)
{
((ownertype*)((char*)this - offsetof(ownertype, prop)))->setfunc(data);
}
};
friend __property##prop;
__property##prop prop
//***************************
// Пример использования
class CValue {
private:
char m_value;
public:
int get_Value() {
return m_value; // Или более сложная логика
}
void put_Value(int value) {
m_value = value; // Или более сложная логика
}
// Свойство Value типа int, использующее функции
// get_Value и put_Value класса CValue
PROPERTY(CValue, int, Value, get_Value, put_Value);
};
int main(int argc, char* argv[]) {
CValue val;
/* Здесь вызывается оператор присваивания переменной-члена val.Value,
и, следовательно, функция val.put_Value() */
val.Value = 50;
/* Здесь вызывается оператор приведения типа переменной-члена val.Value,
и, следовательно, функция val.get_Value() */
int z = val.Value;
return 0;
}
В этом случае ликвидируются как временные затраты (все функции класса property##prop являются встроенными), так и затраты по памяти (к сожалению, только теоретически, так как VC "не умеет" создавать объекты класса нулевой длины). Кроме того, следует заметить, что полученное свойство не является полным эквивалентом declspec. Например, нельзя написать
val.Value += 50;
Этот недостаток присущ и реализации в выпуске 43. Чтобы устранить его, придётся перегружать множество операторов, а потом, возможно, отлавливать множество тонких ошибок. Вот почему я считаю, что "самодельные" свойства представляют скорее теоретический интерес. Это, однако, не повод провозглашать ненужной саму концепцию свойств, аргументируя это мощью и могуществом языка C++, который в них не нуждается.
Александр Шаргин ВОПРОС-ОТВЕТ Как программно создать источник данных? Автор: Игорь ВартановДля этой цели служит функция SQLConfigDataSource(). Она позволяет создать пользовательский или системный источник данных (DSN – DataSource Name). Эта же функция позволяет модифицировать или удалить DSN.
BOOL SQLConfigDataSource(HWND hwndParent, WORD fRequest, LPCSTR lpszDriver, LPCSTR lpszAttributes);
Здесь hwndParent – хэндл окна, которому будут направляться сообщения об ошибках (в случае использования NULL эти сообщения будут подавляться), fRequest – тип выполняемого действия (к примеру, ODBC_ADD_DSN - добавить пользовательский DSN, ODBC_ADD_SYS_DSN - добавить системный DSN), lpszDriver – точное имя драйвера odbc, так, как оно выглядит в диалоге настройки ODBC DSN, например "Microsoft Access Driver (*.mdb)" или "SQL Server". Строка lpszAttributes содержит основные параметры подключения к источнику данных:
• DSN – название создаваемого источника данных
• UID – имя пользователя
• DATABASE – имя базы данных
• PWD – пароль для подключения
Параметры разделены между собой символом ' ', конец строки отмечается дополнительным символом ' '.
DSN=CustomDsn UID=username PWD=password DATABASE=CustomDataBase
Обязательным является имя DSN. Все остальные параметры могут быть запрошены при подключении к источнику данных. Хотя различные драйверы ODBC в этом отношении могут вести себя по-разному – например, для драйвера MS SQLServer обязательным параметром также является и имя сервера.
///////////////////////////////////////////////////////////
//// Пример создания источника данных для
// ODBC драйвера для Microsoft Excel 97
// #include <windows.h>
#include <odbcinst.h>
#pragma comment(lib, "odbccp32")
#pragma comment(lib, "user32")
void main() {
char* driver = "Microsoft Excel Driver (*.xls)";
char* params = "DSN=MyTable DefaultDir=D:\Document "
"DBQ=D:\Document\MyTable.xls ";
// Создадим пользовательский
DSN SQLConfigDataSource(NULL, ODBC_ADD_DSN, driver, params);
}
Надеюсь, для Вас не будет слишком большим сюрпризом узнать, что всю информацию об источниках данных и драйверах ODBC Windows хранит в реестре. А если быть совсем точным, то в ключах
HKEY_CURRENT_USERSoftwareODBCODBC.INI (пользовательские DSN)
HKEY_LOCAL_MACHINESOFTWAREODBCODBC.INI (системные DSN)
HKEY_LOCAL_MACHINESOFTWAREODBCODBCINST.INI (драйверы ODBS)
Информацию о том, как правильно заполнять строку params, можно извлечь самостоятельно, создавая при помощи ODBC-администратора источники данных для различных драйверов Вашей системы и анализируя состав параметров и присвоенные им значения ключей реестра, относящихся к созданным источникам. Надеюсь также, что не сильно шокирую Вас, если скажу, что приведенный выше пример был написан именно так.
Всего доброго и до встречи через неделю!
Алекс Jenter [email protected] Красноярск, 2001. Рассылка является частью проекта RSDN.Программирование на Visual C++
Выпуск №47 от 3 июня 2001 г.
Всем привет!
СТАТЬЯ
Хуки в Win32
Автор: Kyle Marsh
Перевод: Олег Быков
ВведениеВ операционной системе MicrosoftR WindowsNT хуком называется механизм перехвата особой функцией событий (таких как сообщения, ввод с мыши или клавиатуры) до того, как они дойдут до приложения. Эта функция может затем реагировать на события и, в некоторых случаях, изменять или отменять их. Функции, получающие уведомления о событиях, называются фильтрующими функциями и различаются по типам перехватываемых ими событий. Пример – фильтрующая функция для перехвата всех событий мыши или клавиатуры. Чтобы Windows смогла вызывать функцию-фильтр, эта функция должна быть установлена – то есть, прикреплена – к хуку (например, к клавиатурному хуку).