www.adept7.kiev.ua
| Форум| Гостевая| Ссылки| Программы| Исходные тексты| Наши партнеры.|
   
| Главная| Рассылки| Услуги| Библиотека| Новости| Авторам| Программистам| Студентам|
delphi c++ assembler
 
InfoCity
InfoCity - виртуальный город компьютерной документации
www.infocity.kiev.ua
Приглашаем к сотрудничеству авторов книг и статей
компьютерной тематики
Самая большая колекция украинских рефератов.
Постоянно добавляются новые работы.
Загляните : www.referats.kiev.ua
RLE Shop - магазин торгующий за баннеры.
Продайте свой товар или услугу!
www.rleshop.com

 

MS Visual C++ / MFC FAQ


Paul Kalyakin <Paul.Kalyakin@p20.f32.n5029.z2.fidonet.org>
http://www.rusdev.newmail.ru


Вопросы


  • Q1. Как показать ProgressBar на StatusBar'е ?

  • Q2. Как использовать CTreeCtrl для построения дерева каталогов диска, как в Проводнике ?

  • Q3. Есть класс - потомок CListView. Как изменить стиль у объекта CListCtrl, принадлежащего к этому *view (например установить стиль Report)?

  • Q4. Как CString привести к char *?

  • Q5. Какие библиотеки (Freeware/Commercial) существуют для Visual C++ ?

  • Q6. А можно пример консольной программы ?

  • Q7. В созданном мастером (VC 6.0) win32 Console Application попытка вывести русский текст дает кракозяблики.Что делать ?

  • Q8. Пытаюсь из своей программы вызвать Word97, для это делаю несколько импортов и в результате имею кучу ошибок. Как правильно ?

  • Q9. А как отредактировать ресурсы .exe файла ?

  • Q10. Как программно получить номер билда своего приложения в VC++?

  • Q11. Какой функцией можно переключить видеорежим ?

  • Q12. Как вызвать окно выбора папки ?

Ответы


Q1. Как показать ProgressBar на StatusBar'е ?


A1.

Предположим, что вы хотите показать CProgressCtrl на весь StatusBar. Для этого необходимо проделать следующее:
- Выберите пункт меню View - Resource Symbols. Нажмите кнопку New и добавьте новое имя, в нашем примере это будет ID_PROGRBAR.
- В файле MainFrm.cpp найдите объявление массива indicators (он находиться сразу после END_MESSAGE_MAP) и отредактируйте его к следующиему виду

  static UINT indicators[] =
             {
                 ID_PROGRBAR
              };

- В файле _MainFrm.h создайте protected переменную m_bCreated типа BOOL и public переменную m_progress типа CProgressCtl.
- В файле MainFrm.cpp отредактируйте конец функции int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) таким образом:

                  к участку  кода:

                    if (!m_wndStatusBar.Create(this ) ||
                       !m_wndStatusBar.SetIndicators(indicators,
                       sizeof(indicators)/sizeof (UINT)))
                   {
                       TRACE0("Failed to create status bar\n" );
                       return -1; // fail to create
                   }

добавьте следующую строку:

          else {
                m_wndStatusBar.SetPaneInfo(0,ID_PROGRBAR,SBPS_STRETCH,10);
               }

Кроме того, добавьте инициализацию нашей переменной m_bCreated

                    .........
                     m_bCreated=FALSE;
                    ..........

- Теперь мы можем использовать ProgressBar в строке статуса, естественно не забыв создать этот объект. Предположим, у нас есть функция CMainFrame::OnWork(). Она будет выглядеть примерно так:

   void CMainFrame::OnWork()
            {
              RECT rc;
                m_wndStatusBar.GetItemRect(0,&rc);
               if (m_bCreated==FALSE)
               {
                 // создаем  m_progress
                 m_progress.Create(WS_VISIBLE|WS_CHILD, rc,&m_wndStatusBar, 1);
// Устанавливаем размер от 0 до 100
                 m_progress.SetRange(0,100);
                 m_progress.SetStep(1);
                 m_bCreated=TRUE;
                }
                for (int I = 0; I < 100; I++)
                {
                  Sleep(20);
                  m_progress.StepIt();
                }
            }

-Если откомпилировать проект на этой фазе, то все будет работать, но при изменении размера окна линейка ProgressBar'а размеры менять не будет, поэтому необходимо перекрыть событие OnSize:

            void CMainFrame::OnSize(UINT nType, int cx, int cy)
            {
                CFrameWnd::OnSize(nType, cx, cy);
                 if (m_bCreated)
                  {
                      RECT rc;
                      m_wndStatusBar.GetItemRect(0,&rc);
                      m_progress.SetWindowPos(&wndTop, rc.left, rc.top,
                      rc.right - rc.left,rc.bottom - rc.top, 0);
                    }
              }

- Вот теперь все /-))))) Откомпилируйте проект и убедитесь, что все работает.

Q2. Как использовать CTreeCtrl для построения дерева каталогов диска, как в Проводнике ? Неужели необходимо рекурсивно просмотреть диск, а потом прописать ручками все Итемы данного контрола ??


A2. (A. Лисеев Дмитрий. dimik@infopro.spb.su)

Это тормозно и глючно. На больших дисках это займет несколько минут. Если каталоги добавляются или удалются другими приложениями во время работы твоего контрола, то будешь весь в проблемах. Все гораздо проще. Никаких рекурсий. Просматриваем корневой каталог на предмет наличия подкаталогов и создаем итемы первого уровня, в которых создаем по одному фиктивному итему (чтобы крестик был и итем можно было раскрыть).
+ Каталог 1
+ Каталог 2
+ Каталог 3

Как только юзер пытается раскрыть итем, соответствующий некому каталогу, мы удаляем из него фиктивный итем, просматриваем этот подкаталог и добавляем соответствующие итемы со своими фиктивными внутри.
-Каталог 1
+ Каталог 4
+ Каталог 5
+ Каталог 6
+ Каталог 2
+ Каталог 3

Как только юзер закрывает итем, мы удаляем из него все дочерние итемы и обратно добавляем фиктивный. Если структура каталогов изменилась, для обновления юзеру достаточно просто закрыть и открыть соответствующую ветку. Именно так и работает "Проводник".

Q3. Есть класс - потомок CListView. Как изменить стиль у объекта CListCtrl, принадлежащего к этому *view (например установить стиль Report) ?


A3. Для этого пишите в OnInitialUpdate вашего вида
void CMyListView::OnInitialUpdate()
{
 ......
        CListView::OnInitialUpdate();

    CListCtrl& theCtrl = GetListCtrl();
    DWORD dwStyle=GetWindowLong(theCtrl.m_hWnd,GWL_STYLE);
    SetWindowLong(theCtrl.m_hWnd,GWL_STYLE,dwStyle|LVS_REPORT);
 ....
A3. (by Pavel Nazin 2:5020/1053.21)

Гораздо проще перекрыть PreCreateWindow (лучше всего воспользоваться ClassWizard-ом) и поковырять переданный по ссылке CREATESTRUCT типа такого:

BOOL CMyListView::PreCreateWindow(CREATESTRUCT& cs)
{
    cs.style|=LVS_REPORT;//так мы добавляем стиль
    cs.style&=LVS_REPORT;//а вот так снимаем

    return CMyListView::PreCreateWindow(cs);
}

Q4. Как CString привести к char * ? _


A4. (by Yuri Khodin 2:5020/1200.20)
#include <atlbase.h>
USES_CONVERSION;
 CString strData(_T("Some Data"));
 char* lpszString = T2A((LPTSTR)(LPCTSTR)strData);
A4. (by Paul Kalyakin 2:5029/3.29 hjobyf@mail.ru)
CString tmp_str;
char* st;

st=tmp_str.GetBuffer(tmp_str.GetLength())

важно то, что если с tmp_str что-либо сделать, то необходимо опять получить указатель на внутренний буфер CString.

Q5. Какие библиотеки Freeware/Commercial существуют для Visual C++ ? _


A5.
1- BCG Control Library (freeware)
    http://msnhomepages.talkcity.com/WindowsWay/stasl/index.html

2- CJLibrary (freeware)
    http://www.codejock.com

Stringray Software (commercial) www.stingray.com Фирма Stringray Software производит библиотеки для Visual C++ (MFC, ATL):
1. Stingray Objective Toolkit (PRO) - набор различных компонентов для MFC и ATL
2. Stingray Objective Grid (PRO) - мощная сетка данных с возможностями, близкими к Excel. Дружит с базами данных (через DAO,ADO,ODBC). Можно использовать для ввода данных в таблицы БД и для вывода/печати простых отчётов.
3. Stingray Objective Chart - средство для построения диаграмм
4. Stingray Objective Views - средство для создания Visio-подобных интерфейсов (при помощи векторной графики)
5. Stingray Objective Edit - текстовый редактор с подсветкой синтаксиса

кроме этих, есть и другие продукты
- Dundas Software (commercial) http://www.dundas.com Фирма Dundas Software производит библиотеки для Visual C++ (MFC):
1. Dundas Ultimate Toolbox - набор компонентов для MFC, по составу несколько отличающийся от Stingray Objective Toolkit.
2. Dundas Ultimate Grid - сетка данных, конкурент Stingray Objective Grid.
3. Dundas TCP/IP - реализация протоколов POP3,NEWS и т.п.
4. Dundas Chart - диаграммы и другие продукты

Q6.А можно пример консольной программы ? _


A6. by Alexander Fedorov (2:5030/437.74)
#include <windows.h>
#include <stdlib.h>


void main()
 {
 HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
 SMALL_RECT srct;
 CHAR_INFO chiBuffer[160];
 COORD coord1, coord2;
 char ddd[666];
 CharToOem("2:5095/38 - злобный ламерюга", ddd);
 DWORD cWritten;
 coord1.Y = 0; coord1.X = 0;
 hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
 WriteConsoleOutputCharacter(hStdout, ddd, lstrlen(ddd), coord1, cWritten);
 for (int i = 0; i {
 WORD wColors = 1 + i * 3;
 coord1.X = i;
 WriteConsoleOutputAttribute(hStdout, , 1, coord1, cWritten);
 }
 srct.Top = 0; srct.Left = 0; srct.Bottom = 1; srct.Right = 79;
 coord1.Y = 0; coord1.X = 0;
 coord2.Y = 1; coord2.X = 80;
 ReadConsoleOutput(hStdout, chiBuffer, coord2, coord1, );
 for (i = 0; i {
 srct.Left = (SHORT)((double)(79 - lstrlen(ddd)) * rand() / RAND_MAX);
 srct.Top = (SHORT)((double)25 * rand() / RAND_MAX);
 srct.Bottom = srct.Top + 1;
 WriteConsoleOutput(hStdout, chiBuffer, coord2, coord1, );
 }
 Sleep(10000);

Q7. В созданном мастером (VC 6.0 ) win32 Console Application попытка вывести русский текст дает кракозяблики.Что делать ? _


A7. by Dmitriy Reznitskiy (2:5020/1452.112)

CharToOem, OemToChar - оно?

Q8. Пытаюсь из своей программы вызвать Word97, для это делаю несколько импортов и в результате имею кучу ошибок. Как правильно ? _


A8. by Igor Tkachoff (2:5037/9.37)

// Office.h

#define Uses_MSO2000_

 #ifdef Uses_MSO2000
 // for Office 2000
 #import <mso9.dll>
 #import <vbe6ext.olb>
 #import <msword9.olb> rename("ExitWindows","_ExitWindows")
 #import <excel9.olb> rename("DialogBox","_DialogBox") \
 rename("RGB","_RGB") \
 exclude("IFont","IPicture")
 #import <dao360.dll> rename("EOF","EndOfFile") rename("BOF","BegOfFile")
 #import <msacc9.olb>

#else
 // for Office 97
 #import <mso97.dll>
 #import <vbeext1.olb>
 #import <msword8.olb> rename("ExitWindows","_ExitWindows")
 #import <excel8.olb> rename("DialogBox","_DialogBox") \
 rename("RGB","_RGB") \
 exclude("IFont","IPicture")
 #import <DAO350.DLL> \
 rename("EOF","EndOfFile") rename("BOF","BegOfFile")
 #import <msacc8.olb>

#endif
<>pКаталоги проставь сам, если надо. Просто я предпочитаю сваливать все библиотеки в одну кучу. А еще лучше сделать #import один раз, а затем подключать #include "тыры-пыры.tlh".
P.S. С 2000'ным аккуратнее. Некоторые методы (типа Run, Open, Add) имеют новую версию. И если хочешь совместимость с 97 то следует вызывать старые версии, которые называются типа RunOld и т.п.

Q9. А как отредактировать ресурсы .exe файла ? _


A9.

Это возможно лишь под NT.

Q10. Как программно получить номер билда своего приложения в VC++? _


A10. by Pavel Zolotuhin (2:5025/60.15)

Штатной возможности нет, поскольку не все одинаково трактуют понятие "номер билда" и не все одинаково его используют. Однако большинство людей используют для хранения номера билда конкретного файла ресурсы типа VERSIONINFO, откуда эту информацию можно потом получить (для отображения в диалоге "О программе" :-) с помощью функций из version.dll.

Упрощенно говоря, информация о версии файла хранится в VERSIONINFO в виде четырех чисел, значимость которых убывает слева направо. Например, для mfc42.dll из поставки Win2k версия файла выглядит как 6.0.8665.0. Здесь первая цифра, как я понимаю, совпадает с версией продукта (MSVC 6), вторая означает подверсию (MSVC 6.0), третья - номер билда, а четвертая - я не знаю. В своих dll-ках и exe-шниках Microsoft постоянно использует эту схему, я - тоже. Обычно для автоматического увеличения номера версии используются макросы Visual Studio (== скрипты на VBScript), ковыряющие файл ресурсов проекта. Эти макросы либо связываются с кнопкой на тулбаре MSDev, либо вызываются из обработчика события Application_BeforeBuildStart в файле макросов. Примеры подобных макросов горой лежат на девелоперских сайтах, наподобие www.codeguru.com. Для себя я сделал собственный, который реализует номер билда в указанном выше смысле. Вот его исходник (должен работать на MSVC6SP3).

 Sub IncVersion()
 'DESCRIPTION: Increments file version
      Dim oDoc
      Dim iVer

      Set oDoc = Documents.Open(Application.ActiveProject &".rc", "Text")
      if oDoc Is Nothing Then
          Exit Sub
      End If

      oDoc.Selection.FindText "FILEVERSION", dsMatchCase
      if Len(oDoc.Selection) = 0 Then
          oDoc.Close dsSaveChangesNo
          Set oDoc = Nothing
          Exit Sub
      End If
      oDoc.Selection.EndOfLine
      oDoc.Selection.FindText ",", dsMatchBackward
      oDoc.Selection.CharLeft
      oDoc.Selection.WordLeft dsExtend
      iVer = oDoc.Selection
      iVer = iVer + 1
      oDoc.Selection = iVer

      oDoc.Selection.FindText """FileVersion""", dsMatchCase
      if Len(oDoc.Selection) = 0 Then
          oDoc.Close dsSaveChangesNo
          Set oDoc = Nothing
          Exit Sub
      End If
      oDoc.Selection.EndOfLine
      oDoc.Selection.FindText ",", dsMatchBackward
      oDoc.Selection.CharLeft
      oDoc.Selection.WordLeft dsExtend
      iVer = oDoc.Selection
      iVer = iVer + 1
      oDoc.Selection = iVer

      oDoc.Close dsSaveChangesYes
      Set oDoc = Nothing

End Sub

Q11. Какой функцией можно переключить видеорежим ?


A11. by Alexander Shargin (2:5030/852.22)

Этим занимается ChangeDisplaySettings(...);

Вот тебе пример, который устанавливает разрешение 640x480 (24 bit):

=== Cut ===
   DEVMODE md;
   ZeroMemory(&md, sizeof(md));
   md.dmSize = sizeof(md);
   md.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
   md.dmBitsPerPel = 24;
   md.dmPelsWidth = 640;
   md.dmPelsHeight = 480;
   ChangeDisplaySettings(&md, 0);
=== Cut ===

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

Q12. Как вызвать окно выбора папки ?


A12.

Воспользуйтесь следующей функцией:

BOOL FGetDirectory(LPTSTR szDir)
{ BOOL fRet;
   TCHAR szPath[MAX_PATH];
   LPITEMIDLIST pidl;
   LPITEMIDLIST pidlRoot;
   LPMALLOC lpMalloc;
   BROWSEINFO bi =
       {
       NULL,
       NULL,
       szPath,
       "Выберите папку",
       BIF_RETURNONLYFSDIRS,
       NULL,
       0L,
       0
      };
   if (0 != SHGetSpecialFolderLocation(HWND_DESKTOP, CSIDL_DRIVES, &pidlRoot))
     return FALSE;
   if (NULL == pidlRoot)
     return FALSE;
   bi.pidlRoot = pidlRoot;
   pidl = SHBrowseForFolder(&bi);
   if (NULL != pidl)
     fRet = SHGetPathFromIDList(pidl, szDir);
   else
     fRet = FALSE; // Get the shell's allocator to free PIDLs
   if (!SHGetMalloc(&lpMalloc) && (NULL != lpMalloc))
   {
     if (NULL != pidlRoot)
     {
       lpMalloc->Free(pidlRoot);
     }
     if (NULL != pidl)
     {
       lpMalloc->Free(pidl);
     }
lpMalloc->Release();
}
return fRet;
}

LPTSTR PszAlloc(int cch)
{
return (LPTSTR) LocalAlloc(LMEM_FIXED, sizeof(TCHAR) * (cch+1));
}

bool PszDeAlloc(HLOCAL mem_ptr)
{
return (LocalFree(mem_ptr)==NULL) ? true : false;
}

Затем, при необходимости предложить пользователю выбрать папку используйте примерно такой код:

....
LPTSTR fname;
fname=PszAlloc(250);
FGetDirectory(fname);
......
PszDeAlloc((HLOCAL)fname);

HomePage для этого FAQ - http://www.rusdev.newmail.ru


Автор и координатор проекта: Михаил Пинкус  
Дизайн: Tangram Design Studio  

Используются технологии uCoz
 

Rambler's Top100 Rambler's Top100

©  Adept Design Studio

Используются технологии uCoz