C++ C++ C# C# ASP.NET Security ASP.NET Security ASM ASM Скачать Скачать Поиск Поиск Хостинг Хостинг  
  Программа для работы с LPT портом...
Язык: .NET — ©Alexey...
  "ASP.NET Atlas" – AJAX в исполнении Micro...
Язык: .NET — ©legigor@mail.ru...
  "Невытесняющая" Многопоточность...
Язык: C/C++ — ©...
  01.05.2010 — Update World C++: Сборник GPL QT исходников
  15.12.2007 — Весь сайт целиком можно загрузить по ссылкам из раздела Скачать
Хостинг:
Windows 2003, ASP.NET 2.0
бесплатный и от 80 руб./мес


   Отправить письмо
Кулабухов Артем, Беларусь




 Visual C++ FAQ #1 / FAQs / Visual C++

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


void CMainFrame::OnNewIcon()

{

// Прочитать икону из ресурса

HICON newIcon= AfxGetApp()->LoadIcon(IDI_ICON1);

SetIcon(newIcon,TRUE); //Установить её

}


Разумеется, иконка с идентификатором IDI_ICON1 должна быть среди ресурсов вашего проекта.


2. Как заменить меню в SDI-приложении?


В обработчике для смены меню пишем приблизительно следующий код:


void CMainFrame::OnMenuNewMenu()

{

CMenu* cm=GetMenu();

cm->DestroyMenu(); //разрушаем старое меню

cm->LoadMenu(IDR_NEW_MENU); //загружаем новое из ресурса

SetMenu(cm); //Устанавливаем новое меню

m_hMenuDefault = cm->GetSafeHmenu();

cm->Detach();

}


Разумеется, новое меню с ресурсом IDR_NEW_MENU должно быть определено.


3. Как добраться до StatusBar из класса документа?


CMainFrame* pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd;

CStatusBar* pStatusBar = &pFrame->m_wndStatusBar;


Далее пишем всё, что нам надо, например устанавливаем в нулевую панель некую надпись:


pStatusBar->SetPaneText(0,"Некая надпись");


Обратите внимание, что для нашей цели мы используем два шага - сначала мы добираемся до окна-рамки нашего приложения, а затем - до строки состояния (которая принадлежит классу окна-рамки (CMainFrame)).


Также обратите внимание, что переменную m_wndStatusBar надо будет либо объявить как public, либо объявить класс документа дружественным в классе CmainFrame.


4. Как сохранить размер клиентской области при видимой/невидимой строке состояния?


void CMainFrame::OnViewStatusBar()

{

//Выясняем, видима ли строка состояния

BOOL bStatusBar=m_wndStatusBar.GetStyle() & WS_VISIBLE;

//Выясняем текущие размеры окна

CRect r;

GetWindowRect(&r);

//В зависимости от видимости/невидимости строки состояния

//изменяем размер окна

if(bStatusBar){

r.bottom-=18;

}

else{

r.bottom+=18;

}

MoveWindow(r);

//Изменяем видимость строки состояния

m_wndStatusBar.ShowWindow(!bStatusBar);

RecalcLayout();

}


5. Как программно изменить разрешение экрана?


Вот пример консольной программы, изменяющей разрешение экрана на 600 на 800 с глубиной цвета в 16 бит:


#include <iostream.h>

#include <windows.h>

void main(){

DEVMODE md;

ZeroMemory(&md, sizeof(md)); //обнуляем структуру md

md.dmSize = sizeof(md);

md.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

md.dmBitsPerPel = 16;

md.dmPelsWidth = 800;

md.dmPelsHeight = 600;

ChangeDisplaySettings(&md,NULL); //изменяем разрешение экрана

}


6. Как превратить CString в char*?


Проблема в том, что переменную типа char* легко присвоить переменной типа CString, но обратное присваивание делаться не хочет. Пример одного из возможных способов:


#include <iostream.h>

#include <afx.h>

void main(){

CString s="123";

char* ch;

//копируем s в ch

ch=s.GetBuffer(s.GetLength());

cout<<ch<<"\n";

}


7. Как использовать один bitmap для вывода нескольких разных картинок?


Задача такая - у вас есть один bitmap, в котором содержится много картинок. Мы хотим вывести на экран в неком окне не весь bitmap, а лишь его часть. Делается это с помощью метода BitBlt класса CDC:


void CTestView::OnDraw(CDC* pDC)

{

CTestDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

CDC dcDC;

CBitmap cb;

cb.LoadBitmap(IDR_BITMAP1);

dcDC.CreateCompatibleDC(pDC);

dcDC.SelectObject(cb);

//выводим правую половину bitmap'а

pDC->BitBlt(0,0,30,30,&dcDC,30,0,SRCCOPY);

//выводим левую половину bitmap'а

pDC->BitBlt(30,0,30,30,&dcDC,0,0,SRCCOPY);

}


В приведенном примере подразумевается, что в наш проект включен bitmap с идентификатором IDR_BITMAP1 размером 60 на 30. Выглядит он приблизительно так:



После запуска в окне покажется следующее:



Т. е. мы вывели части нашего bitmap'а по отдельности (правый - слева, а левый - справа). Самое существенное здесь - это метод BitBlt класса CDC:


...

pDC->BitBlt(0,0,30,30,&dcDC,30,0,SRCCOPY);

...


Для нас интересны следующие его параметры: первые два (0 и 0) - это координаты вывода изображения на нашей форме (вернее в контексте устройства). Вторая пара (30 и 30) - это размер вырезаемой области из нашего bitmap'а (каждый раз мы вырезаем по квадратику). Третья пара (параметры номер 6 и 7, у нас они равны 30 и 0) - это координаты левого верхнего угла вырезаемой области из нашего bitmap'а.


8. Как переместить кнопку Пуск (Start)?


Сделать это совсем нетрудно. Например, для консольного приложения это можно сделать так:


#include <windows.h>

void main(){

HWND hwndToolBar=FindWindowEx(NULL, NULL, "Shell_TrayWnd", NULL);

HWND hwndStartButton=FindWindowEx(hwndToolBar, NULL, "Button", NULL);

MoveWindow(hwndStartButton,100,1,56,22, TRUE);

}


После запуска программы кнопка Start сдвинется на новое место:


Пару слов про то, что наш код делает. В строке


...

HWND hwndToolBar=FindWindowEx(NULL, NULL, "Shell_TrayWnd", NULL);

...


в переменную hwndToolBar записывается хендл на панель задач (кажется, именно так она называется по-русски).


В следующей строке мы ищем кнопку Start на нашей панели задач:


...

HWND hwndStartButton=FindWindowEx(hwndToolBar, NULL, "Button", NULL);

...


Хендл для этой кнопки запишется в переменную hwndStartButton.


И, наконец, в последней строке


...

MoveWindow(hwndStartButton,100,1,56,22, TRUE);

...


мы сдвигаем нашу кнопку куда захотим.



9. Как поместить bitmap на форму?


Вот два способа сделать это. Каждый способ предполагает, что у нас есть bitmap с идентификатором IDB_BITMAP1.


Способ первый:


void CBitmapView::OnDraw(CDC* pDC)

{

// TODO: add draw code for native data here

CBitmap bitmap;

BITMAP bmp;

bitmap.LoadBitmap(IDB_BITMAP1);

bitmap.GetObject(sizeof(BITMAP), &bmp);

pDC->DrawState(CPoint(0,0),

CSize(bmp.bmWidth,bmp.bmHeight),bitmap, DST_BITMAP);

}


Способ второй - использую функцию BitBlt. Он рассмотрен в вопросе 7.



10. Как сделать фон у надписи прозрачным?


Если выводить текст методом TextOut, то фон у букв не совпадает с цветом формы, что не очень красиво. Например, следующий фрагмент


void CSomeView::OnDraw(CDC* pDC)

{

CSomeView* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

CBrush *pBr=new CBrush;

pBr->CreateSolidBrush(RGB(0, 0, 255));

pDC->SelectObject(pBr);

pDC->Rectangle(0, 0, 100, 100);

pDC->TextOut(10, 10, "Text");

}


даст следующий результат:




Если же мы добавим одну строчку:


...

pDC->Rectangle(0, 0, 100, 100);

pDC->SetBkMode(TRANSPARENT);

pDC->TextOut(10, 10, "Text");

...


то результат будет таким:



11. Как изменить цвет фона у SDI-приложения?


Это надо делать в методе PreCreateWindow для класса вида. Вот код:


BOOL CBitmapView::PreCreateWindow(CREATESTRUCT& cs)

{

// TODO: Modify the Window class or styles here by modifying

// the CREATESTRUCT cs

cs.lpszClass = AfxRegisterWndClass(0, 0, (HBRUSH)COLOR_HIGHLIGHT, 0);

return CView::PreCreateWindow(cs);

}


А вот результат:





12. Что делать при исчезновении классов из ClassView?


Иногда при работе с Visual C++ куда-то деваются классы на вкладке ClassView. Причина этого не ясна, и это явный глюк. Иногда помогает следующее - перейдите на вкладку FileView, далее найдите заголовочный файл для пропавшего класса, двойным щелчком перейдите в окно кода для его, внесите некоторые незначительные изменения (например, добавьте лишний пробел), и сохраните. После этого пропавший класс должен появится вновь.


В ответе на этот вопрос принимал участие Андрей Евдокимов.



13. Как поменять иконку у приложения?


Для смены иконки откройте ее в редакторе иконок в Visual C++. Для этого, естественно, переходим на вкладку Resource, и далее щелкаем на идентификаторе иконки.


Теперь внимание! У приложения присутствуют иконки двух размеров - 32 на 32 и 16 н 16. Та, которя появлятся для нашей формы, имеет размер 32 на 32. Поэтому сначала смените ее размер на 16 на 16:



Изменяем нашу иконку и запускаем приложение. Программа покажется с новой иконкой.



14. Как задать число элементов в ComboBox'е?


Если вы просто разместите combobox на форме, то при запуске у него ниспадающий список будет коротким:



Для того, чтобы увеличить длину списка, просто на этапе разработки щелкните на прямоугольнике со стрелочкой в правой части combobox'а и затем потяните за черный квадратик-маркер для достижения нужного размера:



После этого ваш combobox будет показывать большее число элементов.


15. Почему в ClassWizard'е не появляются идентификаторы для радиокнопок?


Проблема скорей всего в том, что ни для одной из кнопок не был задан флажок Group. Ставим его (только для первого элемента в каждой группе радиокнопок):



Теперь наш идентификатор появился на вкладке Member Variables Class Wizard'а.



16. Почему в ClassWizard'е не появляются идентификаторы для label'ов?


Дело в том, что по умолчанию label имеет идентификатор IDC_STATIC. Такой идентификатор (один на всех) дается всем элементам, про которые предполагается, что они не будут изменяются в программе. Такой же идентификатор имеет, например, элемент Picture. Для того, чтобы идентификатор для label'а появился на вкладке Member Variables, просто измените его на какой-нибудь другой. После этого он появится в ClassWizard'е и с label'ом можно будет делать все что захотите - изменять и т. п.



17. Почему мое немодальное диалоговое окно не появляется?


Скорей всего в конструкторе диалога в его свойствах вы не задали флажок Visible. В результате диалог хоть и создается, но остается невидимым. Установите этот флажок:



После этого диалог должен появляться.



18. Почему в Visual C++ пропадают подсказки?


Это глюки VC++. Для их ликвидации можно использовать Visual Assist. Это, правда, не бесплатно, но есть 30-и дневная пробная версия.



19. Как сделать, чтобы static обрабатывал сообщения Windows?


Задача такая - мы хотим, что бы static (например, label) мог обрабатывать сообщения Windows. Для этого мы должны сделать две вещи - во-первых, мы должны изменить идентификатор нашего static'а на что-нибудь отличное от IDC_STATIC (например, IDC_STATIC1). И во-вторых, мы должны отметить на вкладке Styles флажок Notify:



После этого наш static сможет принимать сообщения Windows. Например, если мы щелкнем на нем (на этапе разработки), то нам будет предложенно задать имя для обработчика сообщения WM_LBUTTONDOWN.



20. Как создать полноэкранное окно?


Распахнуть окно на полный экран можно так:


AfxGetMainWnd()->ShowWindow(SW_SHOWMAXIMIZED);


Гораздо интереснее сделать это по нажатии на некоторую клавишу. Например, можно это сделать принажатии на ESC. Для этого сначала щелкаем на классе главного диалогового окна (вкладка ClassView) правой кнопкой мыши и выбираем Add Virtual Function, в появившемся окне New Virtual Override for class ... ищем PreTranslateMessage и двойным щелчком перекидываем ее в правый listbox. В появившейся заготовке пишем следующий код:


BOOL CMyDlg::PreTranslateMessage(MSG* pMsg)

{

if(pMsg->message == WM_KEYDOWN) //Если нажата клавиша...

{

if(pMsg->wParam == VK_ESCAPE) //...и эта клавиша - ESC

{

//то распахиваем окно на весь экран

AfxGetMainWnd()->ShowWindow(SW_SHOWMAXIMIZED);

return TRUE;

}

}

return CDialog::PreTranslateMessage(pMsg);

}



21. Как создать окно без заголовка?


Для этого надо убрать из стилей такого окна стиль WS_CAPTION. Сделать это можно разными способами. Самый быстрый - это использование метода ModifyStyle класса CWnd. Этот метод можно использовать как для исключения, так и для вклчения разных стилей. Вот пример, показывающий, как убрать заголовок окна по нажаию на некоторую кнопку:


void CTestDlg::OnButton1()

{

// TODO: Add your control notification handler code here

ModifyStyle(WS_CAPTION, 0);

}


У метода ModifyStyle два обязательных параметра. Первый задает то, что должно быть убрано из стилей окна, второй - что должно быть добавлено. Если убирать или добавлять ничего не надо, то в соответствующий параметр надо записать ноль.



22. Как написать два класса, использующие друг друга?


Проблема вот в чем. Есть два класса - для определенности назавем их CFirst и CSecond. В CFirst есть укзазатель на экземпляр второго класса, а в CSecond - указатель на экземпляр первого. И как это все должно работать - какой класс писать сначала?


Делаем это так:


Заголовочный файл для первого класса:


class CSecond;

class CFirst

{

public:

CFirst();

~CFirst();

...

CSecond* m_pSecond;

};


Файл реализации для первого класса:


#include "First.h"

#include "Second.h"

CFirst::CFirst()

{

m_pSecond = new CSecond;

}

CFirst::~CFirst()

{

delete m_pSecond;

}


Заголовочный файл для второго класса:


class CFirst;

class CSecond

{

public:

CSecond();

...

CFirst* m_pFirst;

};


Файл реализации для второго класса:


#include "Second.h"

#include "First.h"

CFirst::CFirst()

{

...

}

CFirst::~CFirst()

{

...

}



23. Как с помощью checkbox'а отключить/включить другой элемент?


Сначала получаем ссылку на другой элемент (пользуясь GetDlgItem), затем делаем все что захотим. Вот пример для кнопки с идентификатором IDC_BUTTON1:


void CTestDlg::OnCheck1()

{

static BOOL b;

CWnd* pBtn=GetDlgItem(IDC_BUTTON1);

pBtn->EnableWindow(b);

b=!b;

}



24. Как быстро удалить класс?


Для удаления класса проще всего удалить из проекта файлы *.h и *.cpp этого класса (пользуясь вкладкой FileView). Физически файлы на диске остаются (так что код не пропадет ;)), на вкладке же ClassView их уже не будет.



25. Чем отличается BOOL и bool?


BOOL и bool, несмотря на похожесть написания - разные типы данных.


bool - это тип данных C/C++. Это означает, что его поддерживает любой компилятор для любой платформы. Хоть для Windows программируете, хоть под Linux - работать программа с таким типом данных должна везде одинаково.


BOOL же - это тип данных, специфичный для платформы Windows.


Две константы для этит типов (истина и ложь) тоже пишуться по-разному. Для типа bool это будут true и false, для типа BOOL - TRUE и FALSE соответственно. Запомнить это достаточно легко - пришем или все строчными буквами, или все прописными.


Для использования типа BOOL надо добавить include:


#include <windows.h>


Вместо этого include'а можно использовать и другие (включающие этот).


У этих типов данных разный размер. Выяснить это можно с помошью оператора sizeof. Для этого достаточно написаить что-то вроде:


int k1=sizeof(BOOL), k2=sizeof(bool);


Так что не путайте эти типы данных. Если в параметрах или в возвращаемом значении некоторой функции используется BOOL, то и используйте переменную такого типа, если bool - то другого. Иногда написание вместо одного из этих типов другого может приветси к краху программы.


26. Как закрыть все окна в MDI-приложении?


Например, так:


void CMainFrame::OnAllClose()

{

//Указатель на дочернее окно

CMDIChildWnd* pWnd;

while(pWnd=MDIGetActive()) //Пока есть дочерние окна

{

pWnd->SendMessage(WM_CLOSE); //Закрываем

}

}


OnAllClose() - это имя обработчика (скажем, для нажатия на пункт меню).



27. Как сделать пункт меню серым?


Вот код (заготовку делаем ClassWizard'ом - на вкладке MessageMaps выбираем идентификатор меню и далее в Messages выбираем UPDATE_COMMAND_UI):


void CMainFrame::OnUpdateOptionsColor(CCmdUI* pCmdUI)

{

// TODO: Add your command update UI handler code here

pCmdUI->Enable(m_b);

}


Разумеется, переменная m_b типа BOOL где-то должна быть определена. Если она равна FALSE, то пункт меню отключается: