Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Поcобие_БЕЛОВ_Графический_интерфейс_API

.pdf
Скачиваний:
141
Добавлен:
18.03.2016
Размер:
2.75 Mб
Скачать

291

pPage[1].dwFlags = PSP_USETITLE | PSP_DLGINDIRECT;

pPage[1].pResource = (DLGTEMPLATE*)CreateDlg1(hwnd); pPage[1].pfnDlgProc = (DLGPROC)DlgProd; pPage[1].pszTitle = "Список";

pHeader.dwSize = sizeof(PRQPSHEETHEADER); pHeader.dwFlags =PSH_PROPSHEETPAGE | PSH_USECALLBACK;

pHeader.hwndParertt = hwnd; pHeader.pszCaption = "Изменение свойств приложения";

pHeader.nPages = sizeof(pPage)/sizeof(PROPSHEETPAGE); pHeader.ppsp = (LPCPROPSHEETPAGE)pPage;

pHeader.pfnCallback=(PFNPROPSHEETCALLBACK)PSCallback;

PropertySheet(&pHeader);

LocalFree(LocalHandle(pPage[0].pResource));

LocalFree(LocaIHandle(pPage[1].pResource)); return 0;

}

return 0;

}

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}

WORD* CreateDlgO( HWND hwnd)

{ char const caption! ]=" Изменение режима работы приложения";

char const stattxt[ ]="Укажите один из режимов:";

char const modeoff[ ]="Завершить работу приложения"; char const modedat[ ]="Перезагрузить данные";

char const modepsw[ ]="Сменить имя пользователя"; //Выделяем блок памяти для записи шаблона WORD *p,

*pdlgtemplate;

pdlgtemplate=p=(PWORD)LocalAlloc(LPTR,4000); int cxChar, cyChar;

{ TEXTMETRIC tm; HDC hdc=GetDC(hwnd); GetTextMetrics(hdc,&trn); ReleaseDC(hwnd.hdc); cxChar=tm.tmAveCharWidth+1 ; cyChar=tm.tmHeight+tm.tmExternalLeading;

292

}

DWORD dlgunit =GetDialogBaseUnits(); int dlgwunit=LOWORD(dlgunit), dlghunit=HIWORD(dlgunit);

cxChar=cxChar*4/dlgwunit;cyChar=cyChar*8/dlghunit; int wDIg, hDIg, wItem, hItem, left, top;

DWORD IStyle;

//Записываем в шаблон данные панели

IStyle = DS.MODALFRAME | WS_POPUPWINDOW | WS_CAPTION;

wDlg=lstrlen(caption)*cxChar; hDlg=cyChar*8; DlgTemplate(p, IStyle, 7,0,0/wDlg, hDIg, (LPSTR)caption);

//Далее добавляем записи для элементов управления

//1

hItem=cyChar; top=left=hItem/2; hItem+=left; wItem=(wDlg-left-left);

IStyle = WS_CHILD | WS_VISIBLE | BS.GROUPBOX | WS_TABSTOP;

DlgItemTemplate(p, IStyle, left, top, wItem, 4*hItem+left, ID_STATICO,(LPSTR)"button",(LPSTR)stattxt);

//2

wItem=lstrlen(modeoff)*cxChar+10; top+=hItem; IStyle = BS_AUTORADIOBUTTON | WS_CHILDfWS_VISIBLE | WS_TABSTOP; DlgItemTemplate(p, IStyle, hItem, top, wItem, hItem, ID_BUTTON1, (LPSTR)"button", (LPSTR)modeoff); //3

wItem=lstrlen(modedat)*cxChar+10;

top+=hItem; IStyle = BS_AUTORADIOBUTTON | WS_CHILD | WSJ/ISIBLE;

DlgItemTemplate(p, IStyle, hItem, top, wItem, hItem, ID_BUTTON2, "button", (LPSTR)modedat);

//4

wItem=lstrlen(modepsw)*cxChar+10;

top+=hItem; IStyle = BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE;

DlgItemTemplate(p, IStyle, hItem, top, wItem, hItem, ID_BUTTON3, (LPSTR)"button", (LPSTR)modepsw);

293

//5 wItem=(wDlg-left-left-hItem-hItem)/3; top+=h!tem+hItem/2+left;

IStyle = BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP; DlgItemTemplate(p, IStyle, left, top, wItem, hItem, IDOK,(LPSTR)"button",(LPSTR)"Да");

//6

IStyle = BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP;

DlgItemTemplate(p, IStyle, left+wItem+hItem, top, wItem, hItem, IDCANCEL,(LPSTR)"button",(LPSTR)"Отмена");

//7

DlgItemTemplate(p, IStyle, left+wItem+hItem+wItem+hItem, top, wItem, hItem, ID_HELP, (LPSTR)"button",(LPSTR)"Справка");

return pdlgtemplate;

}

WORD* CreateDlg1( HWND hwnd)

{char const caption[ ]="Модальная диалоговая панель"; char const stattxt[ ]="Выбранная строка -";

WORD *p, *pdlgtemplate; pdlgtemplate=p=(PWORD)LocalAlloc(LPTR,4000); int cxChar, cyChar;

{

TEXTMETRIC tm; HDC hdc=GetDC(hwnd);

 

GetTextMetrics(hdc,&tm);

 

ReleaseDC(hwnd,hdc);

 

cxChar=tm.tmAveCharWidth+1;

 

cyChar=tm.tmHeight+tm.tmExternalLeading;

}

DWORD dlgunit =GetDialogBaseUnits(); int dlgwunit=LOWORD(dlgunit), dlghunit=HIWORD(dlgunit); cxChar=cxChar*4/dlgwunit; cyChar=cyChar*8/dlghunit;

int wDlg, hDIg, wItem, hItem, left, top; DWORD IStyle;

//Записываем в шаблон данные панели

IStyle = DS_MODALFRAME | WS_POPUPWINDOW |

294

WS_CAPTION; wDlg=lstrien(caption)*cxChar; hDlg=cyChar*9;

DlgTemplate(p, IStyle, 5,0,0, wDlg, hDIg, (LPSTR)caption);

//Добавляем записи для элементов управления

//1

hItem=cyChar; top=left=hItem/2; hItem+=left; wItem=lstrlen(stattxt)*cxChar;

IStyle = SS_LEFT | WS_CHILD | WS_VISIBLE; DlgItemTemplate(p, IStyle, left, top, wItem, hItem, -1, (LPSTR)"static",(LPSTR)stattxt);

//2

DlgItemTemplate(p, IStyle, left+wItem, top, wItem, hItem, ID_STATIC1, (LPSTR)"static",(LPSTR)"");

//3

top+=hItem;

IStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | LBS_STANDARD | LBS_DISABLENOSCROLL; DlgItemTemplate(p, IStyle, left, top, wItem, hItem*4, ID_LISTBOX,(LPSTR)"listbox",(LPSTR)"\0");

//4

wItem=wDlg-wItem-h Item; left+=left+lstrlen(stattxt)*cxChar;

IStyle = BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP;

DlgItemTemplate(p, IStyle, left, top, wItem, hItem, IDOK, (LPSTR)"button",(LPSTR) "Готово");

//5

top += hItem+hItem;

IStyle = BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP;

DlgItemTemplate(p, IStyle, left, top, wItem, hItem, IDCANCEL, (LPSTR)"button",(LPSTR)"Выход");

return pdlgtemplate;

}

LRESULT CALLBACK DlgProcO(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)

{switch (msg)

{ caseWM_COMMAND:

{ switch (LOWORD(wParam))

295

{case IDOK:

case IDCANCEL:

{return TRUE;}

}

return FALSE;

}

}return FALSE;

}

LRESULT CALLBACK DlgProc1(HWND hdig, UINT msg, WPARAM wParam, LPARAM lParam)

{switch (msg)

{caseWMJNITDIALOG:

{HWND hListBox=GetDlgItem(hdlg,ID_LISTBOX); SendMessage(hListBox, WM_SETREDRAW,

FALSE, OL);

SendMessage(hListBox, LB_ADDSTRlNG, 0, (LPARAM)(LPSTR)"Зеленый"); SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)(LPSTR)"Красный"); SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)(LPSTR)"Розовый"); SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)(LPSTR)"Пурпурный"); SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)(LPSTR)"Синий"); SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)(LPSTR)"Желтый"); SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)(LPSTR)"Белый");

SendMessage(hListBox,WM_SETREDRAW,TRUE,0L); InvalidateRect(hListBox, NULL, TRUE); return TRUE;

}

case WM_NOTIFY:

{LPNMHDR pn=(LPNMHDR)lParam; switch (pn->code)

{ casePSN_SETACTIVE:

{ MessageBoxtfidlg, "PSN SETACTIVE", "WM_NOTIFY",MB_OK);

return FALSE;

296

}

case PSN_APPLY:

{MessageBox(hdlg,"PSN_APPLY", "WM_NOTIFY",MB_OK);

return FALSE;

}

case PSN_QUERYCANCEL:

{MessageBox(hdlg,

"PSN_QUERYCANCEL", "WM_NOTIFY",MB_OK); return FALSE;

}

case PSN_KILLACTIVE:

{MessageBox(hdlg,

"PSN_KILLACTIVE", "WM_NOTIFY",MB_OK); return FALSE;

}

}return FALSE;

}

caseWM_COMMAND:

{switch (LOWORD(wParam))

{case IDOK:

{int uSelectedItem; char Buffer[256];

HWND hListBox=GetDlgItem(hdlg, ID_LISTBOX); uSelectedItem=(int)SendMessage( hListBox,LB_GETCURSEL,0,0L); if(uSelectedItem != LB_ERR)

{ SendMessage(hListBox, LB_GETTEXT,

uSelectedItem,(LPARAM)Buffer);

SetWindowText(GetDlgItem(hdlg,

ID_STATIC1), (LPCTSTR)Buffer);

}

SendMessage(GetParent(hdlg),

PSM_CHANGED, (WPARAM)(HWND)hdlg, 0L); return TRUE;

}

return FALSE;

297

}

return FALSE;

}

}

return FALSE;

}

Все части текста этого приложения были рассмотрены. Интерес представляют цели, ради достижения которых добавлены некоторые объекты.

1.В установках проекта добавлена библиотека comctl32.1ib.

2.В текст приложения включен файл prsht.h: \

#include <prsht.h>

Эти два пункта обусловлены тем, что блокнот принадлежит к объектам расширенных возможностей Win32.

3. Изменены функции создания диалоговых панелей:

WORD* CreateDlgO(HWND);

WORD* CreateDlgl(HWND);

Теперь они в памяти создают шаблон панели и возвращают указатель на этот блок памяти.

4. Появился глобальный дескриптор вспомогательного окна: static HWNDhForDIg;

В теле функции этого окна с именем WndForDlg создается блокнот, причем окно hForDlg за время работы приложения ни разу не появляется на экране. Перечислим основные причины использования этого окна:

1)в теле функции окна можно хранить статически описанные локальные данные для работы с панелью. Так, уже на этапе создания окна hForDlg можно было создать шаблоны панелей и инициировать другие данные блокнота;

2)в функцию окна можно посылать сообщения. Здесь в функцию окна посылается единственное сообщение WMCOMMAND с

параметром LOWORD(wParam)=lD_CREATEDLG от функции окна приложения;

3)блокнот по умолчанию располагается в левом верхнем углу окна-владельца. Окно hForDlg создано, и его можно перемещать куда угодно, т.е. перемещая окно hForDlg, можно управлять расположением блокнота. Здесь с помощью такого приема блокнот отображается в центре экрана. Это происходит на этапе инициализации блокнота, в теле функции повторного вызова:

298

int CALLBACK PSCallback(HWND hdlg.UINT uMsg, LPARAM lParam) { if(uMsg==PSCB_INITIALIZED)

{ RECT re; GetWindowRect(hdlg, &rc);

int l=rc.left, t=rc.top, w=rc.right-l, h=rc.bottom-t; MoveWindow(hForDlg,

(wScreen-w)/2, (hScreen-h)/2, w, h, TRUE); } return 0; }

В теле этой функции определяют габариты окна hdlg блокнота и окно-владелец hForDlg перемещают так, что окно блокнота оказывается приблизительно в центре экрана. Размеры окна-владельца не имеют значения. Так, на месте w и h можно было записать 1:

MoveWindow(hForDlg, (wScreen-w)/2, (hScreen-h)/2,1,1, TRUE); 5. Функция окна приложения функции окна hForDlg посылает

сообщение WM_COMMAND с параметром ID_CREATEDLG:

SendMessage(hForDlg, WM_COMMAND, ID_CREATEDLG, OL);

6.Функция окна hForDlg при обработке этого сообщения создает блокнот из двух страниц. Панели для этих страниц рассмотрены. Отличие появилось во второй диалоговой панели (листинг 6.3). Блокнот не допускает использования главного меню, расположенного ниже заголовка панели. Это ясно, так как у панели на странице блокнота нет области заголовка. Вместо заголовка панели в блокноте имеется только вкладыши или закладки страниц.

Обратите внимание, что блокнот – это панель, созданная на базе шаблона в памяти. Этот шаблон в памяти создается, и указатель на него можно получить в теле функции повторного вызова. Есть еще одна особенность – блокнот сам выбирает размеры панелей страниц. Но это не означает, что не требуется задавать размеры панелей страниц в шаблонах.

7.Основные изменения коснулись функций окон панелей. В качестве примера была разработана функция окна второй страницы. Рассмотрим ее более подробно:

1)на этапе инициализации страницы диалоговой панели заполняется список:

SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)(LPSTR)"Зеленый");

SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)(LPSTR)"Белый");

Внимание! Инициализация выполняется только при первом раскрытии страницы;

2)обработка сообщений от элементов управления мало

299

отличается от прежней обработки. Так, после нажатия кнопки «Готово» из списка берется выбранная строка и помещается во второй статический элемент. В этой части изменений нет. Однако страница должна взаимодействовать с кнопками блокнота. В качестве примера после установки текста второго статического элемента сообщаем блокноту о том, что произошли изменения:

SendMessage(GetParent(hdlg), PSM_CHANGED, (WPARAM)(HWND)hdlg, 0L);

Вэтом операторе функция GetParent возвращает дескриптор окна блокнота, т. е. дескриптор родительского окна для окна hdlg страницы. Окно блокнота, получив сообщение PSMCHANGED, в ответ, разблокирует кнопку «Применить». Обратите внимание, что не вызывается функция EndDialog. Если в теле функции окна страницы вызвать эту функцию, то панель для этой страницы будет пустой;

3)имеется еще одна разновидность взаимодействия между блокнотом и функцией окна страницы. Блокнот посылает уведомительное сообщение WM_NOTIFY функции окна раскрытой страницы. При этом параметр lParam указывает на структуру NMHDR, содержащую информацию о сообщении:

LPNMHDR pn=(LPNMHDR)lParam;

Код уведомительного сообщения зависит от произошедшего события. Так, при активизации страницы уведомительное сообщение содержит код PSNSETACTIVE, а при потере активности код равен PSNKILLACTIVE. При нажатии кнопок ОК или «Применить» код сообщения равен PSNAPPLY, при нажатии кнопки «Отмена» код равен PSNQUERYCANCEL. При этом после нажатия каждой кнопки поступает несколько уведомительных сообщений с различными кодами. Так, после нажатия кнопки ОК сначала поступает сообщение с кодом PSNKJLLACTIVE, а потом – с кодом PSNAPPLY.

6.5.Стандартные диалоговые панели

ВWin32 API существуют функции для создания стандартных диалоговых панелей пользовательского интерфейчас.

6.5.1. Панели для открытия или сохранения файлов

Для создания диалоговых окон открытия или создания файлов и при выборе имени для сохранения файла используются функции

GetOpenFileName и GetSaveFileName.

Функция GetOpenFileName создает стандартную панель выбора

IStructSize;
hwndOwner;
hInstance;
lpstrFilter;
lpstrCusromFilter;
nMaxCustFilter;
nFilterlndex;
lpstrFile;
nMaxFile;
lpstrFileTitle;

300

имен для открытия или создания файлов. Эта панель обеспечивает просмотр дисков, каталогов и списка имен файлов и выбор одного или нескольких имен файлов из списка.

Функция GetOpenFileName объявлена следующим образом:

BOOL GetOpenFileName( LPOPENFILENAME lpofn );

Параметр lpofn указывает на структуру типа OPENFILENAME, которая содержит данные для инициализации панели. После завершения работы функции GetOpenFileName эта структура будет дополнена данными о выбранных именах файлов.

Если пользователь выбрал имя файла и нажал кнопку ОК, возвращаемое значение отлично от нуля. При этом буфер, указанный полем lpstrFile структуры будет содержать полное имя выбранного файла, иначе возвращаемое значение – нуль.

Функция GetSaveFiIeName создает стандартную панель выбора имени для сохранения файла. Эта панель обеспечивает просмотр дисков, каталогов и списка имен файлов и выбор одного имени файла. Эта функция объявлена следующим образом: BOOL GetSaveFiIeName( LPOPENFILENAME lpofn);

Параметр lpofn указывает на структуру типа OPENFILENAME, которая содержит данные для инициализации панели. После завершения работы функции GetSaveFiIeName эта структура будет дополнена данными о выбранном имени файла.

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

Структура OPENFILENAME описана следующим образом: typedef struct {

DWORD

HWND HINSTANC LPCTSTR LPTSTR DWORD DWORD LPTSTR DWORD LPTSTR