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

Материал из Весельчак У
Перейти к: навигация, поиск
Строка 1: Строка 1:
===где найти описание nmake для VC++6?===
+
<br>
В MSDN
+
http://msdn.microsoft.com/library/en-us/vcug98/html/_asug_overview.3a_.nmake_reference.asp
+
===Каким образом можно установить значение переменной для вызывающего процесса/потока из своей собственной DLL? Проблема заключается в том, что несмотря на то, что все линкуется нормально, значение переменной процесса не изменяется, когда я его устанавливаю вручную в библиотеке.===
+
Проблема вызвана тем, что каждая влинкованная libc (одна линкуется в
+
исполняемый файл, ещё одна в dll) содержит свою копию переменной.
+
  
1) Можно воспользоваться динамически подгружаемой библиотекой С runtime.
+
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%B3%D0%B4%D0%B5_%D0%BD%D0%B0%D0%B9%D1%82%D0%B8_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_nmake_%D0%B4%D0%BB%D1%8F_VC%2B%2B6|1 где найти описание nmake для VC++6?]]
Для этого приложение и dll надо компилировать с ключом /MD (или MDd для отладки).
+
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%B4%D0%BB%D1%8F_%D0%B2%D1%8B%D0%B7%D1%8B%D0%B2%D0%B0%D1%8E%D1%89%D0%B5%D0%B3%D0%BE_%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%B0/%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0_%D0%B8%D0%B7_%D1%81%D0%B2%D0%BE%D0%B5%D0%B9_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_DLL|2 значение переменной для вызывающего процесса/потока из своей собственной DLL]]
В таком случае переменная будет общей для приложения и dll.
+
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D0%B7%D0%B0%D0%BA%D1%80%D0%B0%D1%81%D0%B8%D1%82%D1%8C_%D1%84%D0%BE%D0%BD_%D0%BE%D0%BA%D0%BD%D0%B0_CWnd|3 Как закрасить фон окна CWnd?]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B8%D1%82%D1%8C_%2C_%D1%87%D1%82%D0%BE_%D0%BA%D1%83%D1%80%D1%81%D0%BE%D1%80_%D0%BC%D1%8B%D1%88%D0%B8_%D0%B2%D1%8B%D1%88%D0%B5%D0%BB_%D0%B7%D0%B0_%D0%B3%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D1%83_%D0%BE%D0%BA%D0%BD%D0%B0|4 Как определить , что курсор мыши вышел за границу окна?]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:%D0%9A%D0%BE%D0%B3%D0%B4%D0%B0_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%89%D0%B0%D1%8E_%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%BD%D0%B5%D0%BD%D1%82_RichEdit_%D0%BD%D0%B0_%D1%84%D0%BE%D1%80%D0%BC%D1%83%2C_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0_%D0%B7%D0%B0%D0%BF%D1%83%D1%81%D0%BA%D0%B0%D0%B5%D1%82%D1%81%D1%8F_%D0%B8_%D1%82%D1%83%D1%82_%D0%B6%D0%B5_%D0%B7%D0%B0%D0%BA%D1%80%D1%8B%D0%B2%D0%B0%D0%B5%D1%82%D1%81%D1%8F|5 Когда размещаю компонент RichEdit на форму, программа запускается и тут же закрывается. Что здесь не так? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%BE%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA_%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B4%D0%BB%D1%8F_%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D0%BE%D0%B2_%D1%81%D1%80%D0%B0%D0%B7%D1%83|6 Как сделать обработчик сообщения для нескольких контролов сразу?]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%B2%D1%81%D0%B5_%D0%BD%D0%B0%D0%B4%D0%BF%D0%B8%D1%81%D0%B8_%D0%BD%D0%B0_%D1%80%D1%83%D1%81%D1%81%D0%BA%D0%BE%D0%BC_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B5_%D1%82%D0%B5%D1%80%D1%8F%D1%8E%D1%82%D1%81%D1%8F_-_%D0%BF%D0%BE%D0%BA%D0%B0%D0%B7%D1%8B%D0%B2%D0%B0%D1%8E%D1%82%D1%81%D1%8F_%D0%B2%D0%BE%D0%BF%D1%80%D0%BE%D1%81%D0%B8%D0%BA%D0%B8|7 Когда запускаю программу, то все надписи на русском языке теряются - показываются вопросики. Что делать? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D0%B2_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B5_VC6_MFC_%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B8%D1%82%D1%8C_%D0%BF%D1%83%D1%82%D1%8C%2C_%D0%BE%D1%82%D0%BA%D1%83%D0%B4%D0%B0_%D0%B7%D0%B0%D0%BF%D1%83%D1%89%D0%B5%D0%BD_%D0%95%D0%A5%D0%95|8 Как в проекте VC6 MFC получить путь, откуда запущен ЕХЕ? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B8%D1%82%D1%8C_%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF_%D0%BA_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D0%B0%D0%BC_%D0%BD%D0%B0_%D0%BF%D0%B0%D0%BD%D0%B5%D0%BB%D0%B8_CReBar%2C_%D0%BF%D1%80%D0%B8%D0%BD%D0%B0%D0%B4%D0%BB%D0%B5%D0%B6%D0%B0%D1%89%D0%B5%D0%B9_%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D1%83_MainFrame|9 Как получить доступ к контролам на панели CReBar, принадлежащей классу MainFrame? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%B8%D1%82%D1%8C_%D0%B8_%D0%BF%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D1%8C_%D0%BE%D0%B4%D0%B8%D0%BD_%D0%B8%D0%B7_%D1%81%D1%82%D0%B0%D0%BD%D0%B4%D0%B0%D1%80%D1%82%D0%BD%D1%8B%D1%85_%D0%BA%D1%83%D1%80%D1%81%D0%BE%D1%80%D0%BE%D0%B2|10 Как загрузить и показать один из стандартных курсоров? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D0%B7%D0%B0%D0%BF%D1%80%D0%B5%D1%82%D0%B8%D1%82%D1%8C_%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8E_%D0%B7%D0%B0%D0%BA%D1%80%D1%8B%D1%82%D1%8C_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D1%83_%D0%BD%D0%B0%D0%B6%D0%B0%D1%82%D0%B8%D0%B5%D0%BC_%D0%BD%D0%B0_%D0%BA%D1%80%D0%B5%D1%81%D1%82%D0%B8%D0%BA|11 Как запретить пользователю закрыть программу нажатием на крестик? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D1%82%D1%8C_%D0%BD%D0%B0_%D0%B4%D0%B8%D0%B0%D0%BB%D0%BE%D0%B3%D0%B5_%D0%B3%D1%80%D1%83%D0%BF%D0%BF%D1%83_RadioButton-%D0%BE%D0%B2_%D0%B8_%D0%BA%D0%B0%D0%BA_%D0%B7%D0%B0%D0%B4%D0%B0%D1%82%D1%8C_%D0%BF%D0%BE%D1%80%D1%8F%D0%B4%D0%BE%D0%BA_%D0%B8%D1%85_%D0%BE%D0%B1%D1%85%D0%BE%D0%B4%D0%B0_%D0%BA%D0%BB%D0%B0%D0%B2%D0%B8%D1%88%D0%B5%D0%B9_Tab|12 Как создать на диалоге группу RadioButton-ов и как задать порядок их обхода клавишей Tab? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%93%D0%B4%D0%B5_%D0%BB%D1%83%D1%87%D1%88%D0%B5_%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%B0%D0%B2%D0%BB%D0%B8%D0%B2%D0%B0%D1%82%D1%8C_%D0%BD%D0%B0%D1%87%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F_CComboBox|13 Где лучше устанавливать начальные значения CComboBox? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D0%BF%D0%B5%D1%80%D0%B5%D0%B2%D0%B5%D1%81%D1%82%D0%B8_RichEdit_%D0%B2_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC_%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD%D1%8B_%D1%81%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB%D0%BE%D0%B2|14 Как перевести RichEdit в режим замены символов? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D0%B2%D1%8B%D0%B7%D0%B2%D0%B0%D1%82%D1%8C_%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D0%B0_CMainFrame_%28%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%BE%D0%B5_%D0%BE%D0%BA%D0%BD%D0%BE%29_%D0%B8%D0%B7_%D0%BB%D1%8E%D0%B1%D0%BE%D0%B3%D0%BE_%D0%BC%D0%B5%D1%81%D1%82%D0%B0_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D1%8B|15 Как вызвать метод класса CMainFrame (главное окно) из любого места программы? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D0%B7%D0%B0%D0%BF%D1%80%D0%B5%D1%82%D0%B8%D1%82%D1%8C_%D0%BF%D0%BE%D1%8F%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE%D0%BB%D0%BE%D1%81_%D0%BF%D1%80%D0%BE%D0%BA%D1%80%D1%83%D1%82%D0%BE%D0%BA_%D0%BD%D0%B0_CFormView%2C_%D0%BA%D0%BE%D0%B3%D0%B4%D0%B0_%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C_%D0%B4%D0%B5%D0%BB%D0%B0%D0%B5%D1%82_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80_%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BE%D0%BA%D0%BD%D0%B0_%D0%BC%D0%B5%D0%BD%D1%8C%D1%88%D0%B5_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0_%D0%BE%D0%BA%D0%BD%D0%B0_CFormView|16 Как запретить появление полос прокруток на CFormView, когда пользователь делает размер главного окна меньше размера окна CFormView ? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D0%BD%D0%B0%D1%80%D0%B8%D1%81%D0%BE%D0%B2%D0%B0%D1%82%D1%8C_%D0%BF%D1%80%D1%8F%D0%BC%D0%BE%D1%83%D0%B3%D0%BE%D0%BB%D1%8C%D0%BD%D0%B8%D0%BA_%D1%81_%D0%B2%D0%B5%D1%80%D1%82%D0%B8%D0%BA%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%BC_%D1%86%D0%B2%D0%B5%D1%82%D0%BE%D0%B2%D1%8B%D0%BC_%D0%B3%D1%80%D0%B0%D0%B4%D0%B8%D0%B5%D0%BD%D1%82%D0%BE%D0%BC|17 Как нарисовать прямоугольник с вертикальным цветовым градиентом? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D0%BF%D0%BE%D0%B4_Windows_%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D1%82%D1%8C_%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D1%84%D0%B0%D0%B9%D0%BB%D0%B0|18 Как под Windows отслеживать изменение файла? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%95%D1%81%D1%82%D1%8C_%D0%BC%D0%B0%D1%81%D1%81%D0%B8%D0%B2_char%2C_%D0%BA%D0%B0%D0%BA_%D0%BA%D0%BE%D0%BD%D0%B2%D0%B5%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C_%D0%B5%D0%B3%D0%BE_%D0%B2_CString|19 Есть массив char, как конвертировать его в CString? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D0%B7%D0%B0%D1%80%D0%B5%D0%B7%D0%B5%D1%80%D0%B2%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C_%D0%B2_CString_%D0%B1%D1%83%D1%84%D0%B5%D1%80_%D0%BD%D1%83%D0%B6%D0%BD%D0%BE%D0%B9_%D0%B4%D0%BB%D0%B8%D0%BD%D1%8B|20 Как зарезервировать в CString буфер нужной длины? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D0%BF%D0%B5%D1%80%D0%B5%D0%B4%D0%B0%D1%82%D1%8C_%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%B5_%D0%BE%D0%B4%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80_%D0%B2_%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D0%B4%D1%83%D1%80%D1%83_%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0|21 Как передать больше одного параметр в процедуру потока?]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D1%83%D0%B1%D1%80%D0%B0%D1%82%D1%8C_%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%BE%D0%B5_%D0%BC%D0%B5%D0%BD%D1%8E_%D0%B8%D0%B7_CMainFrame|22 Как убрать главное меню из CMainFrame?]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0%D1%8E%D1%89%D0%B0%D1%8F_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0_%D0%BC%D0%BE%D0%B6%D0%B5%D1%82_%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B8%D1%82%D1%8C%2C_%D1%87%D1%82%D0%BE_%D1%8E%D0%B7%D0%B5%D1%80_%D0%B7%D0%B0%D0%B2%D0%B5%D1%80%D1%88%D0%B0%D0%B5%D1%82_%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%83_Windows|23 Как работающая программа может определить, что юзер завершает работу Windows? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D1%81%D0%B4%D0%B5%D0%BB%D0%B0%D1%82%D1%8C_%D0%B2%D1%81%D0%BF%D0%BB%D1%8B%D0%B2%D0%B0%D1%8E%D1%89%D1%83%D1%8E_%D0%BF%D0%BE%D0%B4%D1%81%D0%BA%D0%B0%D0%B7%D0%BA%D1%83_%D0%B4%D0%BB%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D0%B0_CWnd_%D0%B8_%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D0%BE%D0%B2%2C_%D0%BE%D1%82_%D0%BD%D0%B5%D0%B3%D0%BE_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D0%BD%D1%8B%D1%85|24 Как сделать всплывающую подсказку для класса CWnd и классов, от него производных? ]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%9A%D0%B0%D0%BA_%D0%B2_%D0%BE%D1%82%D0%BB%D0%B0%D0%B4%D1%87%D0%B8%D0%BA%D0%B5_V%D0%A1_%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%D0%B5%D1%82%D1%8C_%D1%81%D0%BE%D0%B4%D0%B5%D1%80%D0%B6%D0%B8%D0%BC%D0%BE%D0%B5_std::vector-string-_V|25 Как в отладчике VС просмотреть содержимое std::vector-string- V]]
 +
#[[http://wiki.shelek.ru/index.php/FAQ:WinAPI%2C_VCPP_Part_2:%D0%AF_%D0%B2%D1%8B%D0%B2%D0%BE%D0%B6%D1%83_%D0%BD%D0%B0_%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%BA%D1%81%D1%82_%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B0_%D1%82%D0%B5%D0%BA%D1%81%D1%82._%D0%9A%D0%B0%D0%BA_%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B8%D1%82%D1%8C_%D0%B2_%D0%BF%D0%B8%D0%BA%D1%81%D0%B5%D0%BB%D0%B0%D1%85_%D1%88%D0%B8%D1%80%D0%B8%D0%BD%D1%83_%D0%B8_%D0%B2%D1%8B%D1%81%D0%BE%D1%82%D1%83_%D0%B2%D1%8B%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%81%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB%D0%BE%D0%B2_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%B0|26 Я вывожу на контекст устройства текст. Как определить в пикселах ширину и высоту выведенных символов текста?]]
  
2) Можно в основном модуле программы (тот, который станет .exe) сделать
+
 
"дырку" (backdoor), через которую присваивать переменной (int errno) значение:
+
<br>
<pre>
+
 
__declspec(dllexport) void set_errno(int code)
+
 
 +
----
 +
 
 +
=== где найти описание nmake для VC++6?  ===
 +
 
 +
В MSDN http://msdn.microsoft.com/library/en-us/vcug98/html/_asug_overview.3a_.nmake_reference.asp
 +
 
 +
=== Каким образом можно установить значение переменной для вызывающего процесса/потока из своей собственной DLL? Проблема заключается в том, что несмотря на то, что все линкуется нормально, значение переменной процесса не изменяется, когда я его устанавливаю вручную в библиотеке.  ===
 +
 
 +
Проблема вызвана тем, что каждая влинкованная libc (одна линкуется в исполняемый файл, ещё одна в dll) содержит свою копию переменной.
 +
 
 +
1) Можно воспользоваться динамически подгружаемой библиотекой С runtime. Для этого приложение и dll надо компилировать с ключом /MD (или MDd для отладки). В таком случае переменная будет общей для приложения и dll.
 +
 
 +
2) Можно в основном модуле программы (тот, который станет .exe) сделать "дырку" (backdoor), через которую присваивать переменной (int errno) значение:  
 +
<pre>__declspec(dllexport) void set_errno(int code)
 
{
 
{
 
errno = code;
 
errno = code;
 
}
 
}
 
</pre>
 
</pre>
В dll при подключении к процессу надо извлечь из модуля программы указатель на эту функцию.
+
В dll при подключении к процессу надо извлечь из модуля программы указатель на эту функцию.  
<pre>
+
<pre> typedef void (*SETINT)(int);
typedef void (*SETINT)(int);
+
 
SETINT g_set_errno=0;
 
SETINT g_set_errno=0;
 
void set_errno_in_exe(int code)
 
void set_errno_in_exe(int code)
Строка 39: Строка 70:
 
}
 
}
 
</pre>
 
</pre>
В нужном месте в dll вместо присваивания errno нужно вызывать внешнюю функцию
+
В нужном месте в dll вместо присваивания errno нужно вызывать внешнюю функцию  
<pre>
+
<pre>void inside_dll_func()
void inside_dll_func()
+
 
{
 
{
 
...
 
...
Строка 49: Строка 79:
 
}
 
}
 
</pre>
 
</pre>
 +
=== Как закрасить фон окна CWnd?  ===
  
===Как закрасить фон окна CWnd?===
+
Нужно добавить обработчик сообщения WM_CTLCOLOR  
Нужно добавить обработчик сообщения WM_CTLCOLOR
+
<pre>class CMyDialog&nbsp;: public CDialog
<pre>
+
class CMyDialog : public CDialog
+
 
{
 
{
 
//
 
//
Строка 67: Строка 96:
 
m_back_brush.CreateSolidBrush(RGB(192,186,207));
 
m_back_brush.CreateSolidBrush(RGB(192,186,207));
 
}
 
}
</pre>
+
</pre><pre>HBRUSH CMyDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
<pre>
+
HBRUSH CMyDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
+
 
{
 
{
 
switch(nCtlColor)
 
switch(nCtlColor)
Строка 77: Строка 104:
 
{
 
{
 
//у статиков делаем прозрачный фон
 
//у статиков делаем прозрачный фон
pDC->SetBkMode(TRANSPARENT);
+
pDC-&gt;SetBkMode(TRANSPARENT);
 
//и красный цвет текста
 
//и красный цвет текста
pDC->SetTextColor(RGB(255,0,0));
+
pDC-&gt;SetTextColor(RGB(255,0,0));
+
 
//надо же что-то вернуть :)
+
//надо же что-то вернуть&nbsp;:)
 
return (HBRUSH) (m_back_brush.m_hObject);
 
return (HBRUSH) (m_back_brush.m_hObject);
 
}
 
}
 
break;
 
break;
+
 
 
//диалог
 
//диалог
 
case WM_CTLCOLORDLG:
 
case WM_CTLCOLORDLG:
Строка 94: Строка 121:
 
break;
 
break;
 
}
 
}
+
 
 
//фон по умолчанию
 
//фон по умолчанию
 
return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
 
return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
 
}
 
}
 +
 
</pre>
 
</pre>
 +
=== Как определить , что курсор мыши вышел за границу окна?  ===
  
===Как определить , что курсор мыши вышел за границу окна?===
+
1) Использовать функцию _TrackMouseEvent. Например, есть класс MyST  
1) Использовать функцию _TrackMouseEvent. Например, есть класс MyST
+
<pre>class MyST&nbsp;: public CStatic
<pre>
+
class MyST : public CStatic
+
 
{
 
{
 
bool m_bTrackingNow;
 
bool m_bTrackingNow;
Строка 127: Строка 154:
 
tme.hwndTrack = m_hWnd;//из этого окна
 
tme.hwndTrack = m_hWnd;//из этого окна
 
 
::_TrackMouseEvent(&tme);//"запуск" отслеживания
+
::_TrackMouseEvent(&amp;tme);//"запуск" отслеживания
 
//при выходе курсора за границу окна будет
 
//при выходе курсора за границу окна будет
 
//будет сгенерировано сообщение WM_MOUSELEAVE
 
//будет сгенерировано сообщение WM_MOUSELEAVE
Строка 140: Строка 167:
 
BOOL MyST::PreTranslateMessage(MSG* pMsg)
 
BOOL MyST::PreTranslateMessage(MSG* pMsg)
 
{
 
{
if(pMsg->message==WM_MOUSELEAVE)
+
if(pMsg-&gt;message==WM_MOUSELEAVE)
 
{
 
{
 
//тут обрабатываем
 
//тут обрабатываем
Строка 152: Строка 179:
 
}
 
}
 
</pre>
 
</pre>
2) Для случая, когда надо регулировать время "реакции" на выход за границу
+
2) Для случая, когда надо регулировать время "реакции" на выход за границу  
<pre>
+
<pre>enum
enum
+
 
{
 
{
 
def_TrackTimer_ID = 1000, //ID таймера
 
def_TrackTimer_ID = 1000, //ID таймера
Строка 183: Строка 209:
 
//смотрим, где курсор
 
//смотрим, где курсор
 
POINT pnt;
 
POINT pnt;
if(GetCursorPos(&pnt))
+
if(GetCursorPos(&amp;pnt))
 
{
 
{
 
if(WindowFromPoint(pnt)!=this)
 
if(WindowFromPoint(pnt)!=this)
Строка 194: Строка 220:
 
}
 
}
 
</pre>
 
</pre>
 +
=== Когда размещаю компонент RichEdit на форму, программа запускается и тут же закрывается. Что здесь не так?  ===
  
===Когда размещаю компонент RichEdit на форму, программа запускается и тут же закрывается. Что здесь не так?===
+
Необходимо до начала использования контрола инициализировать работу с классом:  
Необходимо до начала использования контрола инициализировать работу с классом:
+
  
для RichEdit необходимо вызвать функцию AfxInitRichEdit(),
+
для RichEdit необходимо вызвать функцию AfxInitRichEdit(), для RichEdit2 - AfxInitRichEdit2().  
для RichEdit2 - AfxInitRichEdit2().
+
  
Вызывать надо в InitInstance() приложения (в случае для MFC).
+
Вызывать надо в InitInstance() приложения (в случае для MFC).  
===Как сделать обработчик сообщения для нескольких контролов сразу?===
+
 
Если без помощи визарда, то переопределить виртуальную OnCommand()
+
=== Как сделать обработчик сообщения для нескольких контролов сразу? ===
<pre>
+
 
BOOL CMyDialog::OnCommand(WPARAM wParam, LPARAM lParam)  
+
Если без помощи визарда, то переопределить виртуальную OnCommand()  
 +
<pre>BOOL CMyDialog::OnCommand(WPARAM wParam, LPARAM lParam)  
 
{
 
{
WORD wMess=(wParam>>16);//командное сообщение
+
WORD wMess=(wParam&gt;&gt;16);//командное сообщение
int nID=(int)(wParam &0x0000ffff));//ID контрола
+
int nID=(int)(wParam &amp;0x0000ffff));//ID контрола
 
HWND hW=(HWND)lParam;//хендл контрола
 
HWND hW=(HWND)lParam;//хендл контрола
 
 
Строка 246: Строка 272:
 
}
 
}
 
</pre>
 
</pre>
===Когда запускаю программу, то все надписи на русском языке теряются - показываются вопросики. Что делать?===
+
=== Когда запускаю программу, то все надписи на русском языке теряются - показываются вопросики. Что делать? ===
Лечится так: непосредственно после создания проекта открываем дерево ресурсов и в свойствах каждого элемента дерева ставим язык Russian. Если этого не сделать сразу, то все русские буквы при компиляции ресурсов потеряются.
+
 
 +
Лечится так: непосредственно после создания проекта открываем дерево ресурсов и в свойствах каждого элемента дерева ставим язык Russian. Если этого не сделать сразу, то все русские буквы при компиляции ресурсов потеряются.  
 +
 
 +
=== Как в проекте VC6 MFC получить путь, откуда запущен ЕХЕ?  ===
  
===Как в проекте VC6 MFC получить путь, откуда запущен ЕХЕ?===
+
Использовать GetModuleFileName():  
Использовать GetModuleFileName():
+
<pre> TCHAR pszFileName[MAX_PATH];
<pre>
+
TCHAR pszFileName[MAX_PATH];
+
 
pszFileName[0]=0;
 
pszFileName[0]=0;
 
GetModuleFileName(NULL, pszFileName, MAX_PATH);
 
GetModuleFileName(NULL, pszFileName, MAX_PATH);
Строка 263: Строка 290:
 
//stModulePath - содержит путь
 
//stModulePath - содержит путь
 
</pre>
 
</pre>
 
+
=== Как получить доступ к контролам на панели CReBar, принадлежащей классу MainFrame? ===
===Как получить доступ к контролам на панели CReBar, принадлежащей классу MainFrame?===
+
<pre>#include "MainFrm.h"
<pre>
+
#include "MainFrm.h"
+
 
 
 
//CMyApp - класс вашего приложения. theApp - глобальная переменная,
 
//CMyApp - класс вашего приложения. theApp - глобальная переменная,
Строка 276: Строка 301:
 
//Получаем главное окно приложения в любом месте программы
 
//Получаем главное окно приложения в любом месте программы
 
CMainFrame* pMainFrame=(CMainFrame*)(theApp.m_pMainWnd);
 
CMainFrame* pMainFrame=(CMainFrame*)(theApp.m_pMainWnd);
pMainFrame->m_wndDlgBar ....//Делаем что хотим
+
pMainFrame-&gt;m_wndDlgBar ....//Делаем что хотим
 
...
 
...
 
}
 
}
 
</pre>
 
</pre>
===Как загрузить и показать один из стандартных курсоров?===
+
=== Как загрузить и показать один из стандартных курсоров? ===
<pre>
+
<pre>HCURSOR hCursor;
HCURSOR hCursor;
+
hCursor=AfxGetApp()-&gt;LoadStandardCursor(IDC_UPARROW);
hCursor=AfxGetApp()->LoadStandardCursor(IDC_UPARROW);
+
 
if(hCursor)SetCursor(hCursor);
 
if(hCursor)SetCursor(hCursor);
 
</pre>
 
</pre>
идентификаторы стандартных курсоров:
+
идентификаторы стандартных курсоров: IDC_ARROW IDC_IBEAM IDC_WAIT IDC_CROSS IDC_UPARROW IDC_SIZENWSE IDC_SIZENESW IDC_SIZEWE IDC_SIZENS IDC_SIZEALL  
IDC_ARROW
+
 
IDC_IBEAM
+
=== Как запретить пользователю закрыть программу нажатием на крестик? ===
IDC_WAIT
+
 
IDC_CROSS
+
Нужно добавить обработчик сообщений WM_CLOSE - OnClose() - в главное окно программы. Для диалоговых приложений - это главный диалог, для одно- и много-документных - это CMainFrame.  
IDC_UPARROW
+
<pre>void CMainFrame::OnClose()
IDC_SIZENWSE
+
IDC_SIZENESW
+
IDC_SIZEWE
+
IDC_SIZENS
+
IDC_SIZEALL
+
===Как запретить пользователю закрыть программу нажатием на крестик?===
+
Нужно добавить обработчик сообщений WM_CLOSE - OnClose() - в главное окно программы. Для диалоговых приложений - это главный диалог, для одно- и много-документных - это CMainFrame.
+
<pre>
+
void CMainFrame::OnClose()
+
 
{
 
{
 
if(......)
 
if(......)
Строка 311: Строка 326:
 
}
 
}
 
</pre>
 
</pre>
 +
=== Как создать на диалоге группу RadioButton-ов и как задать порядок их обхода клавишей Tab?  ===
  
===Как создать на диалоге группу RadioButton-ов и как задать порядок их обхода клавишей Tab?===
+
Кладём на форму N контролов RadioButton. Затем у первого из группы ставим свойство Group, у остальных в группе - убираем это свойство. Порядок обхода (Tab Order) задаётся так: нажимаем Ctrl+D (загораются номера таб-порядка). Затем щёлкаем элементы в группе в таком порядке, который требуется.  
Кладём на форму N контролов RadioButton. Затем у первого из группы ставим свойство Group, у остальных в группе - убираем это свойство. Порядок обхода (Tab Order) задаётся так: нажимаем Ctrl+D (загораются номера таб-порядка). Затем щёлкаем элементы в группе в таком порядке, который требуется.
+
  
===Где лучше устанавливать начальные значения CComboBox?===
+
=== Где лучше устанавливать начальные значения CComboBox? ===
1) В визарде (новая строка данных - Ctrl+Enter)
+
  
2) В функции OnInitDialog (для диалога) или OnInitialUpdate (для CView)
+
1) В визарде (новая строка данных - Ctrl+Enter)  
  
===Как перевести RichEdit в режим замены символов?===
+
2) В функции OnInitDialog (для диалога) или OnInitialUpdate (для CView)
1) Программно, зная хендл контрола (hWnd):
+
 
 +
=== Как перевести RichEdit в режим замены символов? ===
 +
 
 +
1) Программно, зная хендл контрола (hWnd):  
  
 
::PostMessage(hWnd,WM_KEYDOWN,VK_INSERT,1);
 
::PostMessage(hWnd,WM_KEYDOWN,VK_INSERT,1);
  
2) Пользователь может нажать Insert.
+
2) Пользователь может нажать Insert.  
 +
 
 +
=== Как вызвать метод класса CMainFrame (главное окно) из любого места программы?  ===
 +
 
 +
AfxGetApp()-&gt;m_pMainWnd-&gt; ...&nbsp;;
 +
 
 +
=== Как запретить появление полос прокруток на CFormView, когда пользователь делает размер главного окна меньше размера окна CFormView&nbsp;?  ===
  
===Как вызвать метод класса CMainFrame (главное окно) из любого места программы?===
+
методом SetScaleToFitSize():  
AfxGetApp()->m_pMainWnd-> ... ;
+
<pre>void CMyView::OnInitialUpdate()
===Как запретить появление полос прокруток на CFormView, когда пользователь делает размер главного окна меньше размера окна CFormView ?===
+
методом SetScaleToFitSize():
+
<pre>
+
void CMyView::OnInitialUpdate()
+
 
{
 
{
 
CFormView::OnInitialUpdate();
 
CFormView::OnInitialUpdate();
 
/////////
 
/////////
GetParentFrame()->RecalcLayout();
+
GetParentFrame()-&gt;RecalcLayout();
 
ResizeParentToFit();
 
ResizeParentToFit();
 
SIZE s={0,0};
 
SIZE s={0,0};
Строка 345: Строка 364:
 
}
 
}
 
</pre>
 
</pre>
 +
=== Как нарисовать прямоугольник с вертикальным цветовым градиентом?  ===
  
===Как нарисовать прямоугольник с вертикальным цветовым градиентом?===
+
pdc - указатель на контекст устройства pSize - указатель на структуру SIZE с размером прямоугольника dwdColor1, dwdColor2 - начальный и конечный цвет bySteps - количество шагов градиента (1...255)  
 
+
<pre>//вертикальный градиент
pdc - указатель на контекст устройства
+
pSize - указатель на структуру SIZE с размером прямоугольника
+
dwdColor1, dwdColor2 - начальный и конечный цвет
+
bySteps - количество шагов градиента (1...255)
+
<pre>
+
//вертикальный градиент
+
 
void sFillVertGradientRect(CDC* pdc,SIZE *pSize, COLORREF dwdColor1, COLORREF dwdColor2,BYTE bySteps)
 
void sFillVertGradientRect(CDC* pdc,SIZE *pSize, COLORREF dwdColor1, COLORREF dwdColor2,BYTE bySteps)
 
{
 
{
Строка 364: Строка 378:
 
 
 
//ширина и высота
 
//ширина и высота
W=pSize->cx;
+
W=pSize-&gt;cx;
H=pSize->cy;
+
H=pSize-&gt;cy;
 
 
 
//раскладываем цвета на их составляющие
 
//раскладываем цвета на их составляющие
R1=(BYTE)((dwdColor1&0x000000ff));
+
R1=(BYTE)((dwdColor1&amp;0x000000ff));
G1=(BYTE)((dwdColor1&0x0000ff00)>>8);
+
G1=(BYTE)((dwdColor1&amp;0x0000ff00)&gt;&gt;8);
B1=(BYTE)((dwdColor1&0x00ff0000)>>16);
+
B1=(BYTE)((dwdColor1&amp;0x00ff0000)&gt;&gt;16);
R2=(BYTE)((dwdColor2&0x000000ff));
+
R2=(BYTE)((dwdColor2&amp;0x000000ff));
G2=(BYTE)((dwdColor2&0x0000ff00)>>8);
+
G2=(BYTE)((dwdColor2&amp;0x0000ff00)&gt;&gt;8);
B2=(BYTE)((dwdColor2&0x00ff0000)>>16);
+
B2=(BYTE)((dwdColor2&amp;0x00ff0000)&gt;&gt;16);
 
 
 
//высота разноцветных прямоугольников
 
//высота разноцветных прямоугольников
Строка 384: Строка 398:
 
x1=0;x2=W;y1=0;y2=dh;
 
x1=0;x2=W;y1=0;y2=dh;
 
Rc=R1;Gc=G1;Bc=B1;
 
Rc=R1;Gc=G1;Bc=B1;
for(i=0;i<bySteps;i++)
+
for(i=0;i&lt;bySteps;i++)
 
{
 
{
 
//текущий цвет
 
//текущий цвет
pdc->FillSolidRect(x1,(int)y1,x2-x1,(int)(y2-y1),RGB((BYTE)Rc,(BYTE)Gc,(BYTE)Bc));
+
pdc-&gt;FillSolidRect(x1,(int)y1,x2-x1,(int)(y2-y1),RGB((BYTE)Rc,(BYTE)Gc,(BYTE)Bc));
 
//следующий цвет и координаты
 
//следующий цвет и координаты
 
y1+=dh;y2+=dh;
 
y1+=dh;y2+=dh;
Строка 394: Строка 408:
 
}
 
}
 
</pre>
 
</pre>
пример вызова:
+
пример вызова:  
<pre>
+
<pre> SIZE Size={100,100};
SIZE Size={100,100};
+
sFillGradientRect(&amp;dc,&amp;Size, RGB(200,0,0), RGB(0,200,0),10);
sFillGradientRect(&dc,&Size, RGB(200,0,0), RGB(0,200,0),10);
+
 
</pre>
 
</pre>
 +
=== Как под Windows отслеживать изменение файла?  ===
 +
 +
Использовать функции:
  
===Как под Windows отслеживать изменение файла?===
 
Использовать функции:
 
 
   FindFirstChangeNotification
 
   FindFirstChangeNotification
 
   FindNextChangeNotification
 
   FindNextChangeNotification
 
   FindCloseChangeNotification
 
   FindCloseChangeNotification
  
===Есть массив char[], как конвертировать его в CString?===
+
=== Есть массив char[], как конвертировать его в CString? ===
<pre>
+
<pre> char buf[]="text";
char buf[]="text";
+
 
 
 
//строка должна обязательно заканчиваться нулём.
 
//строка должна обязательно заканчиваться нулём.
Строка 419: Строка 432:
 
txt=buf;
 
txt=buf;
 
</pre>
 
</pre>
 +
=== Как зарезервировать в CString буфер нужной длины?  ===
  
===Как зарезервировать в CString буфер нужной длины?===
+
при помощи методов класса:
  
при помощи методов класса:
 
 
   CString::GetBuffer
 
   CString::GetBuffer
 
   и
 
   и
 
   CString::GetBufferSetLength
 
   CString::GetBufferSetLength
  
Разница между CString::GetBuffer(nLen) и CString::GetBufferSetLength(nLen) в том, что первый возвращает строку не меньше заданной длины, а второй возвращает строку точно равную заданной длине. Обе могут перераспределять память если надо. В обычных случаях лучше GetBuffer.
+
Разница между CString::GetBuffer(nLen) и CString::GetBufferSetLength(nLen) в том, что первый возвращает строку не меньше заданной длины, а второй возвращает строку точно равную заданной длине. Обе могут перераспределять память если надо. В обычных случаях лучше GetBuffer.  
  
Если содержимое буфера менялось, то после этого нужно вызвать CString::ReleaseBuffer с указанием новой длины. Значение -1 в вызове CString::ReleaseBuffer означает, что длина строки будет вычислена автоматом (функцией strlen) в методе."-1" удобно использовать, если известно, что строка заканчивается нулем.
+
Если содержимое буфера менялось, то после этого нужно вызвать CString::ReleaseBuffer с указанием новой длины. Значение -1 в вызове CString::ReleaseBuffer означает, что длина строки будет вычислена автоматом (функцией strlen) в методе."-1" удобно использовать, если известно, что строка заканчивается нулем.  
  
===Как передать больше одного параметр в процедуру потока?===
+
=== Как передать больше одного параметр в процедуру потока? ===
  
Определить структуру с указателями на всё любое,
+
Определить структуру с указателями на всё любое, например:  
например:
+
<pre>struct mystr
<pre>
+
struct mystr
+
 
{
 
{
 
CEdit* pEd;
 
CEdit* pEd;
Строка 444: Строка 455:
 
};
 
};
 
</pre>
 
</pre>
запуск потока:
+
запуск потока:  
<pre>
+
<pre>mystr *pparam=new mystr;//экземпляр не должен быть временным!!!
mystr *pparam=new mystr;//экземпляр не должен быть временным!!!
+
 
memset(pparam,0,sizeof(*pparam));
 
memset(pparam,0,sizeof(*pparam));
pparam->pEd=...;
+
pparam-&gt;pEd=...;
pparam->pdwd=...;
+
pparam-&gt;pdwd=...;
  
 
::AfxBeginThread(thread,pparam);  
 
::AfxBeginThread(thread,pparam);  
Строка 455: Строка 465:
 
//он удалиться в потоке
 
//он удалиться в потоке
 
</pre>
 
</pre>
в потоке:
+
в потоке:  
<pre>
+
<pre>//поток:  
//поток:  
+
 
UINT threadLoader(LPVOID pParam)  
 
UINT threadLoader(LPVOID pParam)  
 
{  
 
{  
Строка 464: Строка 473:
  
 
...
 
...
data.pDlg->...;
+
data.pDlg-&gt;...;
 
(*data.pdwd)=...;
 
(*data.pdwd)=...;
 
...
 
...
 
}
 
}
 
</pre>
 
</pre>
===Как убрать главное меню из CMainFrame?===
+
=== Как убрать главное меню из CMainFrame? ===
<pre>
+
<pre>BOOL CMainFrame::PreCreateWindow(CREATESTRUCT&amp; cs)
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
+
 
{
 
{
 
//обнуляем хендл меню до вызова CFrameWnd::PreCreateWindow
 
//обнуляем хендл меню до вызова CFrameWnd::PreCreateWindow
 
cs.hMenu = 0;
 
cs.hMenu = 0;
 
 
if( !CFrameWnd::PreCreateWindow(cs) )
+
if(&nbsp;!CFrameWnd::PreCreateWindow(cs) )
 
return FALSE;
 
return FALSE;
 
...
 
...
Строка 482: Строка 490:
 
}
 
}
 
</pre>
 
</pre>
 +
=== Как работающая программа может определить, что юзер завершает работу Windows?  ===
  
===Как работающая программа может определить, что юзер завершает работу Windows?===
+
В этот момент всем процессам посылается сообщение WM_QUERYENDSESSION - его и нужно отловить в обработчике OnQueryEndSession(). Если вернуть из обработчика значение 0, то Windows продолжит работу.  
В этот момент всем процессам посылается сообщение WM_QUERYENDSESSION - его и нужно отловить в обработчике OnQueryEndSession(). Если вернуть из обработчика значение 0, то Windows продолжит работу.
+
  
===Как сделать всплывающую подсказку для класса CWnd и классов, от него производных?===
+
=== Как сделать всплывающую подсказку для класса CWnd и классов, от него производных? ===
Допустим, имеется диалог класса CMyDlg. Делаем подсказки для контролов. (для CStatic контролов не забудьте поставить свойство Notify)
+
 
<pre>
+
Допустим, имеется диалог класса CMyDlg. Делаем подсказки для контролов. (для CStatic контролов не забудьте поставить свойство Notify)  
class CMyDlg:puplic CDialog
+
<pre>class CMyDlg:puplic CDialog
 
{
 
{
 
CToolTipCtrl m_ToolTip;//мембер класса CMyDlg
 
CToolTipCtrl m_ToolTip;//мембер класса CMyDlg
Строка 540: Строка 548:
 
}
 
}
 
</pre>
 
</pre>
 +
=== Как в отладчике VС просмотреть содержимое std::vector&lt;string&gt; V  ===
  
===Как в отладчике VС просмотреть содержимое std::vector<string> V===
+
В режиме отладки открываем окно "Watch" (ALT+3) и вставляем выражения:  
В режиме отладки открываем окно "Watch" (ALT+3) и вставляем выражения:
+
 
 
+
V._Myfirst - будет показан первый элемент V._Myfirst+1 - второй V._Myfirst+2 - и т.д.  
V._Myfirst     - будет показан первый элемент
+
 
V._Myfirst+1   - второй
+
=== Я вывожу на контекст устройства текст. Как определить в пикселах ширину и высоту выведенных символов текста? ===
V._Myfirst+2   - и т.д.
+
 
===Я вывожу на контекст устройства текст. Как определить в пикселах ширину и высоту выведенных символов текста?===
+
использовать процедуру API:  
использовать процедуру API:
+
<pre>BOOL GetTextExtentPoint32(
<pre>
+
BOOL GetTextExtentPoint32(
+
 
HDC hdc,// хендл контекста
 
HDC hdc,// хендл контекста
 
LPCTSTR lpString,// выводимая строка
 
LPCTSTR lpString,// выводимая строка
Строка 558: Строка 565:
 
);
 
);
 
</pre>
 
</pre>
 
 
[[Category:FAQ]]
 
[[Category:FAQ]]

Версия 22:46, 3 октября 2008


  1. [где найти описание nmake для VC++6?]
  2. [значение переменной для вызывающего процесса/потока из своей собственной DLL]
  3. [Как закрасить фон окна CWnd?]
  4. [Как определить , что курсор мыши вышел за границу окна?]
  5. [Когда размещаю компонент RichEdit на форму, программа запускается и тут же закрывается. Что здесь не так? ]
  6. [Как сделать обработчик сообщения для нескольких контролов сразу?]
  7. [Когда запускаю программу, то все надписи на русском языке теряются - показываются вопросики. Что делать? ]
  8. [Как в проекте VC6 MFC получить путь, откуда запущен ЕХЕ? ]
  9. [Как получить доступ к контролам на панели CReBar, принадлежащей классу MainFrame? ]
  10. [Как загрузить и показать один из стандартных курсоров? ]
  11. [Как запретить пользователю закрыть программу нажатием на крестик? ]
  12. [Как создать на диалоге группу RadioButton-ов и как задать порядок их обхода клавишей Tab? ]
  13. [Где лучше устанавливать начальные значения CComboBox? ]
  14. [Как перевести RichEdit в режим замены символов? ]
  15. [Как вызвать метод класса CMainFrame (главное окно) из любого места программы? ]
  16. [Как запретить появление полос прокруток на CFormView, когда пользователь делает размер главного окна меньше размера окна CFormView ? ]
  17. [Как нарисовать прямоугольник с вертикальным цветовым градиентом? ]
  18. [Как под Windows отслеживать изменение файла? ]
  19. [Есть массив char, как конвертировать его в CString? ]
  20. [Как зарезервировать в CString буфер нужной длины? ]
  21. [Как передать больше одного параметр в процедуру потока?]
  22. [Как убрать главное меню из CMainFrame?]
  23. [Как работающая программа может определить, что юзер завершает работу Windows? ]
  24. [Как сделать всплывающую подсказку для класса CWnd и классов, от него производных? ]
  25. [Как в отладчике VС просмотреть содержимое std::vector-string- V]
  26. [Я вывожу на контекст устройства текст. Как определить в пикселах ширину и высоту выведенных символов текста?]





Содержание

где найти описание nmake для VC++6?

В MSDN http://msdn.microsoft.com/library/en-us/vcug98/html/_asug_overview.3a_.nmake_reference.asp

Каким образом можно установить значение переменной для вызывающего процесса/потока из своей собственной DLL? Проблема заключается в том, что несмотря на то, что все линкуется нормально, значение переменной процесса не изменяется, когда я его устанавливаю вручную в библиотеке.

Проблема вызвана тем, что каждая влинкованная libc (одна линкуется в исполняемый файл, ещё одна в dll) содержит свою копию переменной.

1) Можно воспользоваться динамически подгружаемой библиотекой С runtime. Для этого приложение и dll надо компилировать с ключом /MD (или MDd для отладки). В таком случае переменная будет общей для приложения и dll.

2) Можно в основном модуле программы (тот, который станет .exe) сделать "дырку" (backdoor), через которую присваивать переменной (int errno) значение:

__declspec(dllexport) void set_errno(int code)
{
	errno = code;
}

В dll при подключении к процессу надо извлечь из модуля программы указатель на эту функцию.

	typedef void (*SETINT)(int);
	SETINT g_set_errno=0;
	void set_errno_in_exe(int code)
	{
		if(g_set_errno) g_set_errno(code);
	}
	
	BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
	{
		HANDLE hModule; // Handle to the main module
		if(fdwReason == DLL_PROCESS_ATTACH )
		{
			hModule = GetModuleHandle(NULL);
			if (hModule == NULL) return FALSE;
			g_set_errno = (SETINT) GetProcAddress(hModule, "set_errno");
		}
		return TRUE;
	}

В нужном месте в dll вместо присваивания errno нужно вызывать внешнюю функцию

void inside_dll_func()
{
	...
	...
	set_errno_in_exe(ERROR_CODE);
	...
}

Как закрасить фон окна CWnd?

Нужно добавить обработчик сообщения WM_CTLCOLOR

class CMyDialog : public CDialog
{
	//
	CBrush m_back_brush;
	...
	...
};

//конструктор
CMyDialog::CMyDialog(): CDialog(CMyDialog::IDD)
{
	//создаём кисть фона
	m_back_brush.CreateSolidBrush(RGB(192,186,207));
}
HBRUSH CMyDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 

{ switch(nCtlColor) { //CStatic-контрол case WM_CTLCOLORSTATIC: { //у статиков делаем прозрачный фон pDC->SetBkMode(TRANSPARENT); //и красный цвет текста pDC->SetTextColor(RGB(255,0,0));

//надо же что-то вернуть :) return (HBRUSH) (m_back_brush.m_hObject); } break;

//диалог case WM_CTLCOLORDLG: { //возвращаем хендл кисти нужного фона return (HBRUSH) (m_back_brush.m_hObject); } break; }

//фон по умолчанию return CDialog::OnCtlColor(pDC, pWnd, nCtlColor); }

Как определить , что курсор мыши вышел за границу окна?

1) Использовать функцию _TrackMouseEvent. Например, есть класс MyST

class MyST : public CStatic
{
	bool m_bTrackingNow;
	...
	...
};
	
//в конструкторе
MyST:MyST()
{
	 m_bTrackingNow=false;
}
	
//в обработчике OnMouseMove запускаем отслеживание
void MyST::OnMouseMove(UINT nFlags, CPoint point)
{
	if(!m_bTrackingNow)
	{
		m_bTrackingNow=true;
		TRACKMOUSEEVENT tme;
		tme.cbSize=sizeof(tme);
		tme.dwFlags=TME_LEAVE;//отслеживаем выход курсора
		tme.hwndTrack = m_hWnd;//из этого окна
	
		::_TrackMouseEvent(&tme);//"запуск" отслеживания
		//при выходе курсора за границу окна будет
		//будет сгенерировано сообщение WM_MOUSELEAVE
	}
	...
	...
	CStatic::OnMouseMove(nFlags,point);
}
	
//ловим сообщение WM_MOUSELEAVE, для этого
//переопределяем виртуальную PreTranslateMessage()
BOOL MyST::PreTranslateMessage(MSG* pMsg)
{
	if(pMsg->message==WM_MOUSELEAVE)
	{
		//тут обрабатываем
		...
		...
		m_bTrackingNow=false;
	}
	...
	...
	return CStatic::PreTranslateMessage(pMsg);
}

2) Для случая, когда надо регулировать время "реакции" на выход за границу

enum
{
	def_TrackTimer_ID		=	1000, //ID таймера
	def_TrackTimer_value	=	50, //миллисекунд
};
	
MyST::MyST()
{
	m_bTrackingNow=false;
}
	
//в обработчике OnMouseMove запускаем таймер
void MyST::OnMouseMove(UINT nFlags, CPoint point)
{
	//перезапуск таймера
	SetTimer(def_TrackTimer_ID,def_TrackTimer_value,0);
	m_bTrackingNow=true;
	...
	...
	CStatic::OnMouseMove(nFlags,point);
}
	
void MyST::OnTimer(UINT nIDEvent)
{
	if(nIDEvent==def_TrackTimer_ID)
	{
		KillTimer(def_TrackTimer_ID);//таймер гасит сам себя
		//смотрим, где курсор
		POINT pnt;
		if(GetCursorPos(&pnt))
		{
			if(WindowFromPoint(pnt)!=this)
			{
				m_bTrackingNow=false;//вышли за окно
			}
		}
	}
	CStatic::OnTimer(nIDEvent);
}

Когда размещаю компонент RichEdit на форму, программа запускается и тут же закрывается. Что здесь не так?

Необходимо до начала использования контрола инициализировать работу с классом:

для RichEdit необходимо вызвать функцию AfxInitRichEdit(), для RichEdit2 - AfxInitRichEdit2().

Вызывать надо в InitInstance() приложения (в случае для MFC).

Как сделать обработчик сообщения для нескольких контролов сразу?

Если без помощи визарда, то переопределить виртуальную OnCommand()

BOOL CMyDialog::OnCommand(WPARAM wParam, LPARAM lParam) 
{
	WORD wMess=(wParam>>16);//командное сообщение
	int nID=(int)(wParam &0x0000ffff));//ID контрола
	HWND hW=(HWND)lParam;//хендл контрола
	
	//смотрим, какой контрол
	switch(nID)
	{
		//кнопки
		case ID_BN1:
		case ID_BN2:
		case ID_BN3:
		{
			//смотрим, какое сообщение
			switch(wMess)
			{
				case BN_CLICKED:{	...	}break;
			}
		}
		break;
	
		//едиты
		case ID_ED1:
		case ID_ED2:
		case ID_ED3:
		case ID_ED4:
		{
			//смотрим, какое сообщение
			switch(wMess)
			{
				case EN_CHANGE:{	...	}break;
				case EN_KILLFOCUS:{	...	}break;
			}
		}
		break;
	}
	
	return CDialog::OnCommand(wParam, lParam);
}

Когда запускаю программу, то все надписи на русском языке теряются - показываются вопросики. Что делать?

Лечится так: непосредственно после создания проекта открываем дерево ресурсов и в свойствах каждого элемента дерева ставим язык Russian. Если этого не сделать сразу, то все русские буквы при компиляции ресурсов потеряются.

Как в проекте VC6 MFC получить путь, откуда запущен ЕХЕ?

Использовать GetModuleFileName():

	TCHAR pszFileName[MAX_PATH];
	pszFileName[0]=0;
	GetModuleFileName(NULL, pszFileName, MAX_PATH);
	CString stModulePath =  pszFileName;
	//ищем первый слеш с конца и удаляем
	//его вместе с именем файла EXE
	int nEnd = stModulePath.ReverseFind('\\');
	stModulePath.Delete(nEnd, stModulePath.GetLength()-nEnd);
	
	//stModulePath - содержит путь

Как получить доступ к контролам на панели CReBar, принадлежащей классу MainFrame?

#include "MainFrm.h"
	
//CMyApp - класс вашего приложения. theApp - глобальная переменная,
//поэтому для доступа к ней используем extern
extern CMyApp theApp;

void CMyView::F()
{
	//Получаем главное окно приложения в любом месте программы
	CMainFrame* pMainFrame=(CMainFrame*)(theApp.m_pMainWnd);
	pMainFrame->m_wndDlgBar ....//Делаем что хотим
	...
}

Как загрузить и показать один из стандартных курсоров?

HCURSOR hCursor;
hCursor=AfxGetApp()->LoadStandardCursor(IDC_UPARROW);
if(hCursor)SetCursor(hCursor);

идентификаторы стандартных курсоров: IDC_ARROW IDC_IBEAM IDC_WAIT IDC_CROSS IDC_UPARROW IDC_SIZENWSE IDC_SIZENESW IDC_SIZEWE IDC_SIZENS IDC_SIZEALL

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

Нужно добавить обработчик сообщений WM_CLOSE - OnClose() - в главное окно программы. Для диалоговых приложений - это главный диалог, для одно- и много-документных - это CMainFrame.

void CMainFrame::OnClose()
{
	if(......)
	{
		//не разрешаем закрыть
		return;
	}
	
	CFrameWnd::OnClose();
}

Как создать на диалоге группу RadioButton-ов и как задать порядок их обхода клавишей Tab?

Кладём на форму N контролов RadioButton. Затем у первого из группы ставим свойство Group, у остальных в группе - убираем это свойство. Порядок обхода (Tab Order) задаётся так: нажимаем Ctrl+D (загораются номера таб-порядка). Затем щёлкаем элементы в группе в таком порядке, который требуется.

Где лучше устанавливать начальные значения CComboBox?

1) В визарде (новая строка данных - Ctrl+Enter)

2) В функции OnInitDialog (для диалога) или OnInitialUpdate (для CView)

Как перевести RichEdit в режим замены символов?

1) Программно, зная хендл контрола (hWnd):

PostMessage(hWnd,WM_KEYDOWN,VK_INSERT,1);

2) Пользователь может нажать Insert.

Как вызвать метод класса CMainFrame (главное окно) из любого места программы?

AfxGetApp()->m_pMainWnd-> ... ;

Как запретить появление полос прокруток на CFormView, когда пользователь делает размер главного окна меньше размера окна CFormView ?

методом SetScaleToFitSize():

void CMyView::OnInitialUpdate()
{
	CFormView::OnInitialUpdate();
	/////////
	GetParentFrame()->RecalcLayout();
	ResizeParentToFit();
	SIZE s={0,0};
	SetScaleToFitSize(s);
	/////////
	...
	...
}

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

pdc - указатель на контекст устройства pSize - указатель на структуру SIZE с размером прямоугольника dwdColor1, dwdColor2 - начальный и конечный цвет bySteps - количество шагов градиента (1...255)

//вертикальный градиент
void sFillVertGradientRect(CDC* pdc,SIZE *pSize, COLORREF dwdColor1, COLORREF dwdColor2,BYTE bySteps)
{
	if(!bySteps)bySteps=1;
	WORD i;
	
	long W,H,x1,x2;
	BYTE R1,G1,B1,R2,G2,B2;
	float dh,dR,dG,dB,y1,y2,Rc,Gc,Bc;
	
	//ширина и высота
	W=pSize->cx;
	H=pSize->cy;
	
	//раскладываем цвета на их составляющие
	R1=(BYTE)((dwdColor1&0x000000ff));
	G1=(BYTE)((dwdColor1&0x0000ff00)>>8);
	B1=(BYTE)((dwdColor1&0x00ff0000)>>16);
	R2=(BYTE)((dwdColor2&0x000000ff));
	G2=(BYTE)((dwdColor2&0x0000ff00)>>8);
	B2=(BYTE)((dwdColor2&0x00ff0000)>>16);
	
	//высота разноцветных прямоугольников
	dh=((float)H)/((float)bySteps);
	//величина шагов составляющих цветов
	dR=(((float)R2)-((float)R1))/((float)bySteps);
	dG=(((float)G2)-((float)G1))/((float)bySteps);
	dB=(((float)B2)-((float)B1))/((float)bySteps);
	//выводим прямоугольники
	x1=0;x2=W;y1=0;y2=dh;
	Rc=R1;Gc=G1;Bc=B1;
	for(i=0;i<bySteps;i++)
	{
		//текущий цвет
		pdc->FillSolidRect(x1,(int)y1,x2-x1,(int)(y2-y1),RGB((BYTE)Rc,(BYTE)Gc,(BYTE)Bc));
		//следующий цвет и координаты
		y1+=dh;y2+=dh;
		Rc+=dR;Gc+=dG;Bc+=dB;
	}
}

пример вызова:

	SIZE Size={100,100};
	sFillGradientRect(&dc,&Size, RGB(200,0,0), RGB(0,200,0),10);

Как под Windows отслеживать изменение файла?

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

  FindFirstChangeNotification
  FindNextChangeNotification
  FindCloseChangeNotification

Есть массив char[], как конвертировать его в CString?

	char buf[]="text";
	
	//строка должна обязательно заканчиваться нулём.
	
	//конвертируем так
	CString txt(buf);
	
	//или так
	CString txt;
	txt=buf;

Как зарезервировать в CString буфер нужной длины?

при помощи методов класса:

  CString::GetBuffer
  и
  CString::GetBufferSetLength

Разница между CString::GetBuffer(nLen) и CString::GetBufferSetLength(nLen) в том, что первый возвращает строку не меньше заданной длины, а второй возвращает строку точно равную заданной длине. Обе могут перераспределять память если надо. В обычных случаях лучше GetBuffer.

Если содержимое буфера менялось, то после этого нужно вызвать CString::ReleaseBuffer с указанием новой длины. Значение -1 в вызове CString::ReleaseBuffer означает, что длина строки будет вычислена автоматом (функцией strlen) в методе."-1" удобно использовать, если известно, что строка заканчивается нулем.

Как передать больше одного параметр в процедуру потока?

Определить структуру с указателями на всё любое, например:

struct mystr
{
	CEdit* pEd;
	CDialog* pDlg;
	DWORD* pdwd;
	int *pn;
};

запуск потока:

mystr *pparam=new mystr;//экземпляр не должен быть временным!!!
memset(pparam,0,sizeof(*pparam));
pparam->pEd=...;
pparam->pdwd=...;

::AfxBeginThread(thread,pparam); 
//тут экземпляр *(pparam) уже нельзя использовать!!!
//он удалиться в потоке

в потоке:

//поток: 
UINT threadLoader(LPVOID pParam) 
{ 
	mystr data=*((mystr*)pParam);
	delete ((mystr*)pParam);//подчищаем память

	...
	data.pDlg->...;
	(*data.pdwd)=...;
	...
}

Как убрать главное меню из CMainFrame?

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	//обнуляем хендл меню до вызова CFrameWnd::PreCreateWindow
	cs.hMenu = 0;
	
	if( !CFrameWnd::PreCreateWindow(cs) )
	return FALSE;
	...
	...
}

Как работающая программа может определить, что юзер завершает работу Windows?

В этот момент всем процессам посылается сообщение WM_QUERYENDSESSION - его и нужно отловить в обработчике OnQueryEndSession(). Если вернуть из обработчика значение 0, то Windows продолжит работу.

Как сделать всплывающую подсказку для класса CWnd и классов, от него производных?

Допустим, имеется диалог класса CMyDlg. Делаем подсказки для контролов. (для CStatic контролов не забудьте поставить свойство Notify)

class CMyDlg:puplic CDialog
{
	CToolTipCtrl m_ToolTip;//мембер класса CMyDlg
	//
};
	
//массив, в котором перечислены идентификаторы
//контролов и тексты подсказок к ним
struct{int ID;const char* pch;} m_a_Tips[]=
{
	{IDC_BUTTON1,"КЫнопка"},
	{IDC_STATIC1,"Текст"},
	//
	{0,0},//признак конца массива
};
	
//в инициализации диалога (хотя, в принципе,
//можно и не тут) создаём и привязываем подсказки
BOOL CMyDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();
	//
	//создаём
	m_ToolTip.Create(this);
	//Привязка подсказок
	for(int i=0; m_a_Tips[i].ID; i++)
	{
		m_ToolTip.AddTool(
			GetDlgItem(m_a_Tips[i].ID),
			m_a_Tips[i].pch);
	}
	
	//включаем показ подсказок
	m_ToolTip.Activate(1);
	...
	...
}
	
//для того, чтобы подсказки отображались как реакция на движение
//курсора мыши, транслируем получаемые окнами сообщения в
//виртуальной PreTranslateMessage()
BOOL CMyDlg::PreTranslateMessage(MSG* pMsg) 
{
	//транслируем
	if(m_ToolTip.m_hWnd)m_ToolTip.RelayEvent(pMsg);
	
	...
	...
	return CDialog::PreTranslateMessage(pMsg);
}

Как в отладчике VС просмотреть содержимое std::vector<string> V

В режиме отладки открываем окно "Watch" (ALT+3) и вставляем выражения:

V._Myfirst - будет показан первый элемент V._Myfirst+1 - второй V._Myfirst+2 - и т.д.

Я вывожу на контекст устройства текст. Как определить в пикселах ширину и высоту выведенных символов текста?

использовать процедуру API:

BOOL GetTextExtentPoint32(
	HDC hdc,// хендл контекста
	LPCTSTR lpString,// выводимая строка
	int cbString,// длина строки в символах
	LPSIZE lpSize// указатель на структуру SIZE, куда 
					//будут помещены размеры
);