faqs.org.ru

 Главная > Программирование > Языки C/C++/Builder >

FAQ по MS Visual C++

From: Paul Kalyakin <Paul.Kalyakin@p20.f32.n5029.z2.fidonet.org>
Date: Fri, 29 Sep 2000 09:17:30 +0400

                     -==MS Visual C++ / MFC FAQ ==-
                      Версия 1.012 от 29.09.2000

                               Вопросы


Q1.  Как показать ProgressBar на StatusBar'е ?
Q2.  Как использовать CTreeCtrl для построения дерева каталогов диска, как в
     Проводнике ?
Q3.  Есть класс - потомок CListView. Как изменить стиль у объекта CListCtrl,
     принадлежащего к этому *view (например установить стиль Report)?
Q4.  Как CString привести к char *?
Q5.  Какие библиотеки (Freeware/Commercial) существуют для Visual C++ ?
Q6.  А можно пример консольной программы ?
Q7.  В созданном мастеpом (VC 6.0) win32 Console Application попытка вывести
     pyсский текст дает кpакозяблики.Что делать ?
Q8.  Пытаюсь из своей программы вызвать Word97, для это делаю несколько
     импортов и в результате имею кучу ошибок. Как правильно ?
Q9.  А как отредактировать ресурсы .exe файла ?
Q10. Как программно получить номер билда своего приложения в VC++?
Q11. Какой фyнкцией можно пеpеключить видеоpежим ?
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)
Гоpаздо пpоще пеpекpыть PreCreateWindow (лучше всего воспользоваться
ClassWizard-ом) и поковыpять пеpеданный по ссылке 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);

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

кpоме этих, есть и дpугие пpодукты

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




==============================================================================

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 - злобный ламеpюга", 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. В созданном мастеpом (VC 6.0 ) win32 Console Application попытка вывести
    pyсский текст дает кpакозяблики.Что делать ? _

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оставь сам, если надо. Пpосто я пpедпочитаю сваливать все
библиотеки в одну кучу. А еще лучше сделать #import один pаз, а затем
подключать #include "тыpы-пыpы.tlh".
P.S. С 2000'ным аккуpатнее. Некотоpые методы (типа Run, Open, Add) имеют новую
веpсию. И если хочешь совместимость с 97 то следует вызывать стаpые веpсии,
котоpые называются типа 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. Какой фyнкцией можно пеpеключить видеоpежим ?

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


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

Вот тебе пpимеp, котоpый yстанавливает pазpешение 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 ===

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

=============================================================================
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

Вернуться в раздел "Языки C/C++/Builder" - Обсудить эту статью на Форуме
Главная - Поиск по сайту - О проекте - Форум - Обратная связь

© faqs.org.ru