Главная страница Случайная страница Разделы сайта АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
💸 Как сделать бизнес проще, а карман толще?
Тот, кто работает в сфере услуг, знает — без ведения записи клиентов никуда. Мало того, что нужно видеть свое раписание, но и напоминать клиентам о визитах тоже.
Проблема в том, что средняя цена по рынку за такой сервис — 800 руб/мес или почти 15 000 руб за год. И это минимальный функционал.
Нашли самый бюджетный и оптимальный вариант: сервис VisitTime.⚡️ Для новых пользователей первый месяц бесплатно. А далее 290 руб/мес, это в 3 раза дешевле аналогов. За эту цену доступен весь функционал: напоминание о визитах, чаевые, предоплаты, общение с клиентами, переносы записей и так далее. ✅ Уйма гибких настроек, которые помогут вам зарабатывать больше и забыть про чувство «что-то мне нужно было сделать». Сомневаетесь? нажмите на текст, запустите чат-бота и убедитесь во всем сами! Спільні елементи керування 4 страница
{public: BOOL InitInstance(); };
// t1.cpp: implementation of the CMain class.
#include < afxwin.h> #include < afxcmn.h> #include " t1.h" #include " resource.h"
#define ID_TREE 400002 #define NUM 5
CMain:: CMain() {Create(NULL, " Використання дерева", WS_OVERLAPPEDWINDOW, rectDefault, NULL, MAKEINTRESOURCE(IDR_MENU1)); InitCommonControls(); RECT r; r.left=r.top=30; r.right=220; r.bottom=200; m_Tree.Create(WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_EDITLABELS | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT, r, this, ID_TREE); InitTree(); }
BEGIN_MESSAGE_MAP(CMain, CFrameWnd) ON_WM_PAINT() ON_COMMAND(ID_TREE_EXPAND, OnExpand) ON_COMMAND(ID_TREE_COLLAPSE, OnCollapse) END_MESSAGE_MAP()
BOOL CApp:: InitInstance() {m_pMainWnd = new CMain; m_pMainWnd -> ShowWindow(m_nCmdShow); m_pMainWnd -> UpdateWindow(); return TRUE; }
CApp App;
HTREEITEM hTreeCtrl[30]; HTREEITEM hTreeCurrent; int i;
void CMain:: InitTree() {TV_INSERTSTRUCT tvs; TV_ITEM tvi; tvs.hInsertAfter=TVI_LAST; tvi.mask=TVIF_TEXT; tvi.pszText=" One"; tvs.hParent=TVI_ROOT; tvs.item=tvi; hTreeCtrl[0]=m_Tree.InsertItem(& tvs); hTreeCurrent=hTreeCtrl[0];
tvi.pszText=" Two"; tvs.hParent=hTreeCtrl[0]; tvs.item=tvi; hTreeCtrl[1]=m_Tree.InsertItem(& tvs);
tvi.pszText=" Three"; tvs.hParent=hTreeCtrl[1]; tvs.item=tvi; hTreeCtrl[2]=m_Tree.InsertItem(& tvs);
tvi.pszText=" Four"; tvs.hParent=hTreeCtrl[2]; tvs.item=tvi; hTreeCtrl[3]=m_Tree.InsertItem(& tvs); tvi.pszText=" Five"; tvs.hParent=hTreeCtrl[2]; tvs.item=tvi; hTreeCtrl[4]=m_Tree.InsertItem(& tvs); i=5; }
void CMain:: OnPaint() {CPaintDC dc(this); TV_ITEM tvi; char str1[40]; char str2[40]; tvi.hItem = hTreeCurrent; tvi.pszText = str1; tvi.cchTextMax = sizeof(str1)-1; tvi.mask=TVIF_TEXT | TVIF_HANDLE; m_Tree.GetItem(& tvi); wsprintf(str2, " Current Selection %s", tvi.pszText); dc.TextOut(2, 220, str2, strlen(str2)); }
void CMain:: OnExpand() {m_Tree.Expand(hTreeCurrent, TVE_EXPAND); } void CMain:: OnCollapse() {m_Tree.Expand(hTreeCurrent, TVE_COLLAPSE); }
5.10.7 Використання елементів перегляду дерев у діалогових вікнах У п. 5.10.2 вже зазначувалося, що послідовність створення елементів перегляду дерев має дещо інший вигляд. Насамперед, він визначається можливістю розмістити та встановити розмір вікна перегляду дерева безпосередньо у шаблоні діалогового вікна. Крім того, необхідно зв’язати ресурси діалогового вікна з відповідним йому об’єктом, також викликати функцію ініціалізації дерева елементів. Усі ці особливості стануть предметом наступної програми. В ній передбачатиметься додавання та вилучення елементів дерева, редагування текстових поміток існуючих вузлів. Додамо, також, що у дереві даних, яке використовуватиметься у прикладі, ми використаємо окрім текстових позначок також і графічні – для надання інтерфейсу програми більшої інформативності. Визначимо такий порядок побудови програми: 1) створити новий проект типу “Win32 Application” з опцією “empty project”; 2) додати у проект ресурс діалогового вікна (ідентифікатор IDD_DIALOG1) із шаблоном ресурсу дерева (ідентифікатор IDC_TREE1, встановлено властивість “Edit labels”), кнопок “Додати” для додавання вузлів (ідентифікатор IDC_BUTTON1), “Вилучити” – для вилучення вузлів дерева (ідентифікатор IDC_BUTTON2), “Редагувати” – для редагування текстових позначок вузлів (ідентифікатор IDC_BUTTON3) із загальним виглядом, наведеним на рисунку 5.13.
Рисунок 5.13 – Вигляд ресурсів програми для діалогового вікна з деревом
3) зберегти файл ресурсів та додати у проект; 4) викликати майстер класів (Class Wizard) та за його допомогою створити клас діалогового вікна CSDialog, відповідний створеним ресурсам; 5) також у Class Wizard, визначити об’єкти, відповідні ресурсу дерева (m_Tree класу CTreeCtrl) та полю редагування (m_Edit типу CEdit); 6) поставити за допомогою Class Wizard у відповідність кнопкам у діалоговому вікні такі функції: OnAdd() – для кнопки “Додати”, OnDelete() – для кнопки “Вилучити”, OnEdit() – для кнопки “Редагувати” (усі – на сторінці “Message map”, повідомлення – BN_CLICKED); також визначити обробку повідомлення WM_INITDIALOG – функцію OnInitDialog() для ініціалізації діалогового вікна (особливості подібних операцій детально описані у п. 5.7.4); 7) через поле структури проекту додати клас прикладки CApp (породжуваний з CWinApp, розташований у файлах SDialog1.h та SDialog1.cpp) та визначити в ньому функцію InitInstance() типу BOOL із таким кодом: BOOL CApp:: InitInstance() {CSDialog a; a.DoModal(); return TRUE; } 8) оголосити глобальний об’єкт прикладки: CApp App; 9) у файлі SDialog.cpp змінити директиви препроцесора #include на такі: #include < afxwin.h> #include < afxcmn.h> #include " resource.h" #include " SDialog.h"
10) натиснувши “Alt+F7” змінити опції проекту на такі, що передбачають використання MFC, спробувати побудувати і виконати проект; у разі успішної побудови та виконання продовжити побудову, інакше – виправити помилки; 11) у клас CSDialog додати об’єкт списку зображень для зберігання пікто-грам, відповідних вузлам дерева:
CImageList m_treeImageList;
12) за допомогою редактора ресурсів створити пікторами вузлів: IDI_ICON1, IDI_ICON2, IDI_ICON2; 13) визначити глобальні змінні для зберігання вузлів дерева:
HTREEITEM hTreeCtrl[30]; // масив дескрипторів вузлів HTREEITEM hTreeCurrent; // дескриптор поточного вузла int i; // кількість вузлів дерева
14) у клас CSDialog додати функцію void InitTree() та визначити її код у вигляді, визначеному прикладом 5.10, здійснити виклик InitTree() з функції ініціалізації діалогового вікна OnInitDialog();
Приклад 5.10 – Ініціалізація дерева для діалогового вікна
void CSDialog:: InitTree() {m_treeImageList.Create(16, 16, FALSE, 3, 0); // створення порожнього списку піктограм // завантаження пікторами кожна розміром 16x16 пікселів HICON hIcon = LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON1)); m_treeImageList.Add(hIcon); // додавання піктограми у список hIcon = LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON2)); m_treeImageList.Add(hIcon); hIcon = LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON3)); m_treeImageList.Add(hIcon); // під’єднання списку піктограм до об’єкта дерева m_Tree.SetImageList(& m_treeImageList, TVSIL_NORMAL);
TV_INSERTSTRUCT tvs; TV_ITEM tvi; tvs.hInsertAfter=TVI_LAST; // встановлення стилів підтримки тексту, піктограм необраного та обраного вузлів дерева tvi.mask=TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.pszText=" One"; // текстова позначка вузла дерева tvi.iImage=0; // код піктограми необраного вузла дерева tvi.iSelectedImage=1; // код піктограми обраного вузла дерева tvs.hParent=TVI_ROOT; tvs.item=tvi; hTreeCtrl[0]=m_Tree.InsertItem(& tvs); hTreeCurrent=hTreeCtrl[0];
tvi.pszText=" Two"; tvi.iImage=0; tvi.iSelectedImage=1; tvs.hParent=hTreeCtrl[0]; tvs.item=tvi; hTreeCtrl[1]=m_Tree.InsertItem(& tvs);
tvi.pszText=" Three"; tvi.iImage=1; tvi.iSelectedImage=2; tvs.hParent=hTreeCtrl[1]; tvs.item=tvi; hTreeCtrl[2]=m_Tree.InsertItem(& tvs); tvi.pszText=" Four"; tvi.iImage=1; tvi.iSelectedImage=2; tvs.hParent=hTreeCtrl[2]; tvs.item=tvi; hTreeCtrl[3]=m_Tree.InsertItem(& tvs);
tvi.pszText=" Five"; tvi.iImage=1; tvi.iSelectedImage=2; tvs.hParent=hTreeCtrl[2]; tvs.item=tvi; hTreeCtrl[4]=m_Tree.InsertItem(& tvs); }
15) реалізувати функції OnAdd(), OnDelete(), OnEdit() у спосіб, наведений у прикладі 5.11:
Приклад 5.11 – Реалізація функцій додавання, вилучення та редагування вузлів
void CSDialog:: OnAdd() {// TODO: Add your control notification handler code here if(! m_Tree.GetSelectedItem()) MessageBox(" Вузол не обрано", " "); // жоден вузол дерева не обрано else {i++; char str[20]; m_Edit.GetWindowText(str, sizeof(str)); if(strlen(str)) {hTreeCurrent=m_Tree.GetSelectedItem(); TV_INSERTSTRUCT tvs; TV_ITEM tvi; tvs.hInsertAfter=TVI_LAST; tvi.mask=TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; tvi.iImage=0; tvi.iSelectedImage=1; tvi.pszText=str; tvs.hParent=hTreeCurrent; tvs.item=tvi; hTreeCtrl[i]=m_Tree.InsertItem(& tvs); hTreeCurrent=hTreeCtrl[i]; InvalidateRect(NULL); } else MessageBox(" Задайте ім’я", " "); // ім’я вузла є порожнім }}
void CSDialog:: OnDelete() {// TODO: Add your control notification handler code here if(! m_Tree.GetSelectedItem()) // жоден вузол дерева не обрано MessageBox(" Вузол не обрано", " "); else {hTreeCurrent=m_Tree.GetSelectedItem(); if(! m_Tree.GetParentItem(hTreeCurrent)) // заборона вилучати корінь дерева MessageBox(" Не можна вилучити корінь", " "); else {m_Tree.DeleteItem(hTreeCurrent); i--; hTreeCurrent=hTreeCtrl[i--]; InvalidateRect(NULL); }}}
void CSDialog:: OnEdit() { // TODO: Add your control notification handler code here hTreeCurrent=m_Tree.GetSelectedItem(); m_Tree.EditLabel(hTreeCurrent); }
16) забезпечити редагування вузлів дерева також і за допомогою натискання правої клавіші миші на будь-якому з вузлів, для чого у Class Wizard вибрати ідентифікатор об’єкта дерева IDC_TREE1 та його повідомлення NM_RCLICK, що дозволить додати функцію OnRclickTree1():
void CSDialog:: OnRclickTree1(NMHDR* pNMHDR, LRESULT* pResult) { // TODO: Add your control notification handler code here hTreeCurrent=m_Tree.GetSelectedItem(); m_Tree.EditLabel(hTreeCurrent); *pResult = 0; } Функція діє так само, як і OnEdit(), аде для її використання необхідно лише обрати вузол, текстову позначку якого необхідно відредагувати. Одна тількі неприємність: результат редагування за допомогою функцій OnEdit(), OnRclickTree1() після задання нової позначки не зберігається і програма не реагує на повідомлення про початок редагування вузла та закінчення процесу редагування (TVN_BEGINLABELEDIT та TVN_ENDLABELEDIT). Для уникнення проблеми додамо обробку цих повідомлень. 17) за допомогою Class Wizard для класу CSDialog оберемо обробку повідомлення WM_NOTIFY і таким чином оголосимо функцію:
BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
Її необхідно реалізувати у зазначений у прикладі 5.12 спосіб:
Приклад 5.12 – Реалізація обробки повідомлення нотифікації у діалоговому вікні
BOOL CSDialog:: OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) {// TODO: Add your specialized code here and/or call the base class TV_DISPINFO* tv_dispInfo = (TV_DISPINFO*) lParam; if (tv_dispInfo-> hdr.code == TVN_BEGINLABELEDIT) CEdit* pEdit = m_Tree.GetEditControl(); else if (tv_dispInfo-> hdr.code == TVN_ENDLABELEDIT) { if (tv_dispInfo-> item.pszText! = NULL) m_Tree.SetItemText(tv_dispInfo-> item.hItem, tv_dispInfo-> item.pszText); } return CDialog:: OnNotify(wParam, lParam, pResult); } Як результат виконання зазначеної послідовності маємо отримати результат, наведений на рисунку 5.14.
Рисунок 5.14 – Вигляд діалогового вікна із реалізацією функцій дерева
Повний тест програми наведено у прикладі 5.13.
Приклад 5.13 – Текст програми із реалізацією дерева у діалоговому вікні
// SDialog.h: header file class CSDialog: public CDialog {public: void InitTree(); CSDialog(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CSDialog) enum { IDD = IDD_DIALOG1 }; CTreeCtrl m_Tree; CImageList m_treeImageList; CEdit m_Edit; //}}AFX_DATA // Overrides ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CSDialog) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); //}}AFX_VIRTUAL // Implementation protected: // Generated message map functions //{{AFX_MSG(CSDialog) virtual BOOL OnInitDialog(); afx_msg void OnAdd(); afx_msg void OnDelete(); afx_msg void OnEdit(); afx_msg void OnRclickTree1(NMHDR* pNMHDR, LRESULT* pResult); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; class CApp: public CWinApp {public: BOOL InitInstance(); CApp(); virtual ~CApp(); };
// SDialog.cpp: implementation file #include < afxwin.h> #include < afxcmn.h> #include " resource.h" #include " SDialog.h"
HTREEITEM hTreeCtrl[30]; HTREEITEM hTreeCurrent; int i;
CSDialog:: CSDialog(CWnd* pParent /*=NULL*/): CDialog(CSDialog:: IDD, pParent) {//{{AFX_DATA_INIT(CSDialog) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT }
void CSDialog:: DoDataExchange(CDataExchange* pDX) {CDialog:: DoDataExchange(pDX); //{{AFX_DATA_MAP(CSDialog) DDX_Control(pDX, IDC_TREE1, m_Tree); DDX_Control(pDX, IDC_EDIT1, m_Edit); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CSDialog, CDialog) //{{AFX_MSG_MAP(CSDialog) ON_BN_CLICKED(IDC_BUTTON1, OnAdd) ON_BN_CLICKED(IDC_BUTTON2, OnDelete) ON_BN_CLICKED(IDC_BUTTON3, OnEdit) ON_NOTIFY(NM_RCLICK, IDC_TREE1, OnRclickTree1) //}}AFX_MSG_MAP END_MESSAGE_MAP()
BOOL CSDialog:: OnInitDialog() {CDialog:: OnInitDialog(); // TODO: Add extra initialization here InitTree(); return TRUE; }
CApp:: CApp(){} CApp:: ~CApp(){}
BOOL CApp:: InitInstance() {CSDialog a; a.DoModal(); return TRUE; }
CApp App; void CSDialog:: OnAdd() {// TODO: Add your control notification handler code here if(! m_Tree.GetSelectedItem()) MessageBox(" Node isn't selected", " "); else {i++; char str[20]; m_Edit.GetWindowText(str, sizeof(str)); if(strlen(str)) { hTreeCurrent=m_Tree.GetSelectedItem(); TV_INSERTSTRUCT tvs; TV_ITEM tvi; tvs.hInsertAfter=TVI_LAST; tvi.mask=TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; tvi.iImage=0; tvi.iSelectedImage=1; tvi.pszText=str; tvs.hParent=hTreeCurrent; tvs.item=tvi; hTreeCtrl[i]=m_Tree.InsertItem(& tvs); hTreeCurrent=hTreeCtrl[i]; InvalidateRect(NULL); } else MessageBox(" You should set unzero name ", " "); }}
void CSDialog:: OnDelete() {// TODO: Add your control notification handler code here if(! m_Tree.GetSelectedItem()) MessageBox(" Node isn't selected", " "); else {hTreeCurrent=m_Tree.GetSelectedItem(); if(! m_Tree.GetParentItem(hTreeCurrent)) MessageBox(" You can't delete the root", " "); else {m_Tree.DeleteItem(hTreeCurrent); i--; hTreeCurrent=hTreeCtrl[i--]; InvalidateRect(NULL); }}}
void CSDialog:: OnEdit() {hTreeCurrent=m_Tree.GetSelectedItem(); m_Tree.EditLabel(hTreeCurrent); }
void CSDialog:: InitTree() {m_treeImageList.Create(16, 16, FALSE, 3, 0); HICON hIcon = LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON1)); m_treeImageList.Add(hIcon); hIcon = LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON2)); m_treeImageList.Add(hIcon); hIcon = LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON3)); m_treeImageList.Add(hIcon); m_Tree.SetImageList(& m_treeImageList, TVSIL_NORMAL);
TV_INSERTSTRUCT tvs; TV_ITEM tvi; tvs.hInsertAfter=TVI_LAST; tvi.mask=TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.pszText=" One"; tvi.iImage=0; tvi.iSelectedImage=1; tvs.hParent=TVI_ROOT; tvs.item=tvi; hTreeCtrl[0]=m_Tree.InsertItem(& tvs); hTreeCurrent=hTreeCtrl[0];
tvi.pszText=" Two"; tvi.iImage=0; tvi.iSelectedImage=1; tvs.hParent=hTreeCtrl[0]; tvs.item=tvi; hTreeCtrl[1]=m_Tree.InsertItem(& tvs);
tvi.pszText=" Three"; tvi.iImage=1; tvi.iSelectedImage=2; tvs.hParent=hTreeCtrl[1]; tvs.item=tvi; hTreeCtrl[2]=m_Tree.InsertItem(& tvs);
tvi.pszText=" Four"; tvi.iImage=1; tvi.iSelectedImage=2; tvs.hParent=hTreeCtrl[2]; tvs.item=tvi; hTreeCtrl[3]=m_Tree.InsertItem(& tvs);
tvi.pszText=" Five"; tvi.iImage=1; tvi.iSelectedImage=2; tvs.hParent=hTreeCtrl[2]; tvs.item=tvi; hTreeCtrl[4]=m_Tree.InsertItem(& tvs); }
void CSDialog:: OnRclickTree1(NMHDR* pNMHDR, LRESULT* pResult) {// TODO: Add your control notification handler code here hTreeCurrent=m_Tree.GetSelectedItem(); m_Tree.EditLabel(hTreeCurrent); *pResult = 0; }
BOOL CSDialog:: OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) {// TODO: Add your specialized code here and/or call the base class TV_DISPINFO* tv_dispInfo = (TV_DISPINFO*) lParam; if (tv_dispInfo-> hdr.code == TVN_BEGINLABELEDIT) CEdit* pEdit = m_Tree.GetEditControl(); else if (tv_dispInfo-> hdr.code == TVN_ENDLABELEDIT) { if (tv_dispInfo-> item.pszText! = NULL) m_Tree.SetItemText(tv_dispInfo-> item.hItem, tv_dispInfo-> item.pszText); } return CDialog:: OnNotify(wParam, lParam, pResult); }
5.11 Використання рядків стану
Рядок стану (або “status bar control”) є горизонтальним вікном, яке звичайно відображується у нижній частині батьківського вікна, у якому відображується інформація про стан параметрів програми. Наприклад, програма Microsoft Word відображує поточну інформацію у формі, наведеній на рис. 5.15.
Рисунок 5.15 – Приклад використання рядка стану
У MFC рядок стану забезпечується за допомогою класу CStatusBarCtrl. Для створення рядка стану необхідно виконати декілька кроків: 1) створити об’єкт типу CStatusBarCtrl у класі вікна програми; 2) викликати функцію Create() для створення вікна рядка стану, приєднати до нього об’єкт класу: Функція Create() класу CStatusBarCtrl має такий вигляд:
BOOL CStatusBar:: Create(CWnd*pParentWnd, DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, UINT nID=AFX_IDW_STATUS_BAR);
де pParentWnd – покажчик на батьківське вікно Windows, dwStyle - стиль рядка стану, nID – ідентифікатор дочірнього вікна панелі інструментів. Окрім стан-дартних стилів для рядка стану визначаються додаткові стилі:
Таблиця 5.12 – Стилі елемента рядка стану
Клас CStatusBarCtrl забезпечується рядом необхідних функцій, серед них зазначимо деякі. Кількість полів у рядку стану визначає функція SetParts():
BOOL CStatusBarCtrl:: SetParts(int nParts, int* pWidths);
де nParts – кількість частин рядка (не може перевищувати 255), pWidths – адреса цілочисельного масиву, який визначає позиції правого краю кожної частини (значення -1 означає, що позиція правого краю частини перевищує правий край керування). Для кожного з визначених полів рядка функція SetText() визначає текстове заповнення:
BOOL CStatusBarCtrl:: SetText (LPCTSTR lpszText, int nPane, int nType);
де lpszText – покажчик на рядок, что встановлюється у полі; nPane – номер поля, до якого встановлюється текст; nType – режим відображення тексту (0 – текст відображується “натиснутим” у полі, SBT_NOBORDERS – текст не має рамки, SBT_OWNERDRAW – текст відображується батьківським вікном, SBT_POPOUT – текст відображується в опуклому вигляді). Для використання у MFC-програмі елемента відображення рядка стану необхідно виконати певну послідовність кроків: 1) створити об’єкт рядка стану; 2) визначити кількість полів рядка стану; 3) визначити текст кожного поля рядка; 4) оновити текст під час змін у роботі програми. Якщо для програми із створенням регулятора гучності звуку (приклад 5.6) передбачити відображення поточних значень гучності у каналах через рядок стану, у програму вносяться такі зміни: 1) у класі діалогового вікна оголошується об’єкт рядка стану: class CSDialog: public CDialog {public: CStatusBarCtrl m_Status; …………………………. }; 2) у функції ініціалізації діалогового вікна фізично створити рядок стану: BOOL CSDialog:: OnInitDialog() { CDialog:: OnInitDialog(); m_sl1.SetPos(50); m_sl2.SetPos(50); m_sl3.SetPos(50); CRect r; GetClientRect(& r); int parts[3]; // три поля for(int i=1; i< =3; i++)parts[i-1]=r.right/3*i; // визначення координат трьох полів m_Status.Create(WS_VISIBLE | WS_CHILD, r, this, 1); m_Status.SetParts(3, parts); return TRUE; } 3) модифікувати обробник OnVScroll() для відображення у рядку стану поточних значень регуляторів лівого, правого каналів, загального регулятора гучності звуку: void CSDialog:: OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { DWORD volume; char str[255]; UINT uRetVal, uNumDevs; if (uNumDevs = waveOutGetNumDevs()) {uRetVal = waveOutGetVolume(0, (LPDWORD)& volume); if(pScrollBar==(CScrollBar*)& m_sl1) {DWORD curVol=MAKELONG((DWORD)0xFFFF/100*m_sl1.GetPos(), HIWORD(volume)); waveOutSetVolume(0, curVol); wsprintf(str, " Лівий канал: %d", m_sl1.GetPos()); // формування тексту поля 0 m_Status.SetText(str, 0, 0); // визначення тексту поля 0 } if(pScrollBar==(CScrollBar*)& m_sl2) {DWORD curVol=MAKELONG(LOWORD(volume), (DWORD)0xFFFF/100*m_sl2.GetPos()); waveOutSetVolume(0, curVol); wsprintf(str, " Правий канал: %d", m_sl2.GetPos()); m_Status.SetText(str, 1, 0); } if(pScrollBar==(CScrollBar*)& m_sl3) {m_sl1.SetPos(m_sl3.GetPos()); m_sl2.SetPos(m_sl3.GetPos()); DWORD curVol=MAKELONG((DWORD)0xFFFF/100*m_sl1.GetPos(), (DWORD)0xFFFF/100*m_sl2.GetPos()); waveOutSetVolume(0, curVol); wsprintf(str, " Лівий канал: %d", m_sl1.GetPos()); m_Status.SetText(str, 0, 0); // запис у перше поле wsprintf(str, " Правий канал: %d", m_sl2.GetPos()); m_Status.SetText(str, 1, 0); // запис у друге поле wsprintf(str, " Загальний: %d", m_sl3.GetPos()); m_Status.SetText(str, 2, 0); // запис у третє поле }} CDialog:: OnVScroll(nSBCode, nPos, pScrollBar); }
Результат роботи модифікованої програми наведений на рисунку 5.16.
Рисунок 5.16 – Регулятор гучності із рядком стану
5.12 Використання закладок
5.12.1 Загальна інформація про закладки Елемент закладка (tab control) зовнішньо нагадує сторінки записника, у якому доступ до кожної сторінки діалогового вікна здійснюється її простим вибором. Редактор ресурсів Visual С++ надає можливості візуального визначення вигляду елемента (зображений на рисунку 5.17).
Рисунок 5.17 – Вигляд елемента закладка
Кожна сторінка закладки може відображати інші елементи керування, і таким чином дозволяє об’єднувати редагування декількох сторінок із властивостями програмних об’єктів. Подібними, але більш розвиненими елементами керування є сторінки властивостей, що ми розглянемо пізніше. У MFC закладка реалізована за допомогою класу CTabCtrl, що так само як і інші спільні елементи керування породжується від класу CWnd і є спадкоємцем його головних властивостей. Послідовність створення закладки як елемента головного вікна програми зазвичай складається з двох кроків: 1) створити об’єкт закладки у класі головного вікна; 2) використати функцію Create() класу CTabCtrl для визначення основних властивостей елемента закладки. Функція Create() класу CTabCtrl має такий прототип:
BOOL CTabCtrl:: Create(DWORD dwStyle, RECT& rect, CWnd* pParentWnd, UINT nID);
де dwStyle – стиль закладки, rect – її розташування та розмір, pParentWnd – покажчик на батьківське вікно (має відрізнятися від NULL), nID – ідентифікатор ресурсу. Під час створення закладки у головному вікні програми використовують стандартні стилі WS_CHILD, WS_VISIBLE, WS_BORDER а також ряд специфічних для об’єкта закладки. Деякі з властивих закладці стилів наведено у таблиці 5.13.
Таблиця 5.13 – Основні стилі елемента закладка
|