Платформа Win32 - Меню и акселераторы
Участников: 3
Страница 1 из 1
Платформа Win32 - Меню и акселераторы
Написание меню
Меню — один из краеугольных камней идеологии Win32 (Windows и ReactOS). Похожие друг на друга меню разрешают пользоваться абсолютно незнакомыми программами, не читая инструкций, и узнавать об из возможностях путём просмотра содержания различных пунктов меню. Попробуем добавить меню и в нашу программу Window.bas.
Но перед тем как перейти к программе демонстрации меню, изучим основные концепции Win32, связанные с меню.
Концепция меню
При создании меню для вашей программы нужно сгруппировать команды, выполняющие однотипные действия. Более того, следует присвоить имена этим группам, которые хорошо знакомы пользователям. Тогда, даже если пользователи впервые работают с вашей программой, они легко разыщут требуемую команду или, по крайней мере, будут знать, где её искать. Ниже приведён список некоторых стандартных названий меню, которые вы можете встретить практически в любой программе, написанной для Windows или ReactOS.
File (Файл). В данную группу помещают все команды, которые работают с файлами. Обычно в этом меню находятся такие команды как New (Создать), Open (Открыть), Close (Закрыть), Save (Сохранить), Save As (Сохранить как) и Print (Печать). Если программа предназначена для активной работы с файлами, в данное меню помещается также список нескольких последних файлов, к которым было обращение. Как правило, самой последней командой данного меню является Exit (Выход).
Edit (Правка). В данную группу помещают команды, предназначенные для редактирования объектов и текста, а также для работы с буфером обмена: Undo (Отменить), Cut (Вырезать), Copy (Копировать), Paste (Вставить), Clear (Очистить), Find (Найти) и Replace (Заменить).
View (Вид). В данную группу меню помещают команды, предназначенные для изменения режимов просмотра документа. Например, в программе текстового процессора OpenOffice Writer в этом меню находятся команды для перехода из обычного режима редактирования (предназначенного для набора текста) в режим разметки страницы, в котором выполняется вёрстка макета. Кроме того, в описываемое меню помещается команда изменения масштаба документа.
Tools (Сервис). В данную группу помещаются команды для запуска даполнительных утилит и программ настройки. Например, в программе текстового процессора в этом меню находятся команды для проверки правописания и грамматики.
Window (Окно). Данная группа меню, как правило, включается в те приложения, которые поддерживают многодокументный интерфейс (MDI). MDI-программы, такие как OpenOffice Writer или Calc, позволяют одновременно работать с несколькими документами. Кроме того, меню Window позволяет в одном месте хранить список открытых документов и быстро переключаться между ними.
Help (Справка). В данное меню включаются команды вызова справочной системы. Обычно в нём можно встретить пункты для вызова
оглавления справочной системы (команда Help Index), поиска нужной темы в справочнике (команда Search), а также вывода информации о программе (команда About), её авторах и правах собственности.
Клавиши быстрого доступа
Клавиши быстрого доступа позволяют перемещаться по системе меню без применения мыши. Если в названии меню предусмотрена клавиша быстрого доступа, то в названии меню она будет подчёркнута (например, буква F в меню File). Для создания клавиши достаточно поместить символ амперсенда (&) перед соответствующей буквой в тексте меню. (Если же нужно, чтобы в названии меню отображался символ &, то введите его дважды - &&.) Старайтесь там, где это возможно, назначать в качестве клавиши быстрого доступа первую букву в названии меню, поскольку именно её чаще всего ожидают увидеть пользователи. В то же время, не стоит использовать первую букву в том случае, если она уже назначена для другого элемента меню.
Вы можете назначить часто используемым командам программы специальные сочетания клавиш ("горячие" клавиши, или акселераторы), дабы часто не обращаться к меню для запуска нужной команды. "Грячие" клавиши позволяют запустить команду после нажатия одной (например, <Delete>) или двух (таких как <Ctrl+S>) клавиш клавиатуры. Правильно назначенные клавиатурные эквиваленты ещё больше ускоряют работу пользователя.
File->New Ctrl+N Создать новый документ
File->Open Ctrl+O Открыть новый документ
File->Save Ctrl+S Сохранить документ
File->Print Ctrl+P Распечатать документ
Edit->Cut Ctrl+X Вырезать
Edit->Copy Ctrl+C Копировать
Edit->Paste Ctrl+V Вставить
Edit->Undo Ctrl+Z Отменить
Edit->Find Ctrl+F Найти
Создание меню
Первое, что нам нужно получить, - это само меню. Его, также как значки, диалоги и другую информацию (вплоть до версии программы), записывают в файлы ресурсов. Файл ресурсов имеет расширение *.RC для текстового файла или *.RES для бинарного файла, созданного специальным компилятором ресурсов (RC, BRCC32, WRC). И те, и другие файлы ресурсов можно редактировать особыми программами, сводящими в дистрибутив C/C++, или с помощью других средств разработки для Windows, но мы не будем создавать слишком сложное меню и напишем RC-файл вручную, например, так:
Полный код программы Window.bas с меню
#Include once "windows.bi"
' Функция, в которой будет происходить
' цикл обработки сообщений
Declare Function WndProc(ByVal hWnd As HWND, ByVal wMsg As UINT, ByVal wParam As WPARAM, ByVal lParam As LPARAM) As LRESULT
''
'' Program Start
''
Dim hInst As HINSTANCE ' Идентификатор нашего процесса
Dim wMsg As MSG ' Сообщения, принимаемые от окна
Dim wc As WNDCLASS ' Структура нашего класса окна
Dim hWnd As HWND ' Идентификатор окна
Dim hAccel As HACCEL ' Идентификатор акселератора
' Получаем идентификатор нашего процесса
hInst = GetModuleHandle(0)
/' Функция Cast приводит выражение из правой части
к типу, указанному в левой части так что запись типа
Cast(ZString Ptr, 14)
получает нужный нам указатель на идентификатор акселератора
'/
' Загружаем "Горячие" клавиши (акселераторы)
hAccel = LoadAccelerators(hInst, Cast(ZString Ptr, 14))
' Создаём структуру класса окна
With wc
' Стиль прорисовки окна
.style = CS_HREDRAW Or CS_VREDRAW
' Адрес функции обработки сообщения, посылаемых окну
.lpfnWndProc = @WndProc
' Дополнительные данные
.cbClsExtra = 0
.cbWndExtra = 0
' Идентификатор процесса, создающего класс окна
.hInstance = hInst
' Значок окна
.hIcon = LoadIcon(0, IDI_APPLICATION)
' Курсор по умолчанию
.hCursor = LoadCursor(0, IDC_ARROW)
' Кисть по умолчанию для отрисовки фона окна
.hbrBackground = Cast(HBRUSH, COLOR_BTNFACE + 1)
' Имя нашего меню из ресурсов
.lpszMenuName = Cast(ZString Ptr, 13)
' Адрес строки с именем класса окна
.lpszClassName = @"FBWindow"
End With
' Регистрируем класс окна
RegisterClass(@wc)
' Создаём окно с именем зарегистрированного класса
hWnd = CreateWindow(@"FBWindow", _ /' Адрес строки с именем класса окна '/
"Пример простого окна с меню", _ /' Заголовок нашего окна '/
WS_OVERLAPPEDWINDOW, _ /' Стиль окна '/
CW_USEDEFAULT, _ /' X-позиция на экране, используем по умолчанию '/
CW_USEDEFAULT, _ /' Y-позиция на экране, используем по умолчанию '/
640, _ /' Ширина нашего окна '/
480, _ /' Высота нашего окна '/
0, _ /' Идентификатор родительского окна, используется если создаваемое окно является дочерним '/
0, _ /' Идентификатор меню из ресурсов программы,
так как мы определили меню в классе окна
то оставляем здесь 0 '/
hInst, _ /' Идентификатор процесса, создающего окно '/
0) /' Дополнительные данные, у нас их нет '/
' Показываем окно
ShowWindow(hWnd, SW_NORMAL)
' Обновляем содержимое окна
' При этом окну посылается сообщение WM_PAINT
UpdateWindow(hWnd)
' Цикл обработки сообщений от окна
Do While GetMessage(@wMsg, 0, 0, 0) <> 0
' Добавляем проверку на нажатие горячих клавиш
If TranslateAccelerator(hWnd, hAccel, @wMsg) = 0 Then
TranslateMessage(@wMsg)
DispatchMessage(@wMsg)
End If
Loop
''
'' Program End
''
'
' Функция для обработки сообщений от окна
'
Function WndProc(ByVal hWnd As HWND, _
ByVal wMsg As UINT, _
ByVal wParam As WPARAM, _
ByVal lParam As LPARAM) As LRESULT
Select Case(wMsg)
Case WM_CREATE
' Здесь должна происходить инициализация
Case WM_COMMAND
' Сообщения от меню
Select Case HiWord(wParam)
Case BN_CLICKED, 1
Select Case LoWord(wParam)
Case 1
' Пункт меню New (создать новый документ)
Case 2
' Пункт меню Open (открыть)
Case 3
' Пункт меню Save (сохранить)
Case 4
' Пункт меню SaveAs (сохранить под другим именем)
Case 5
' Пункт меню Exit (закрыть программу)
' Уничтожаем окно
DestroyWindow(hWnd)
Case 6
' Пункт меню About (о программе)
Case 7
' Пункт меню Undo (отменить)
Case 8
' Пункт меню Cut (вырезать в буфер обмена)
Case 9
' Пункт меню Copy (копировать в буфер обмена)
Case 10
' Пункт меню Paste (вставить из буфера обмена)
Case 11
' Пункт меню Clear (очистить текстовое поле)
Case 12
' Пункт меню SelectAll (выделить весь текст)
End Select
End Select
Case WM_CLOSE
' Сообщение о закрытии окна
' Окно нужно уничтожить
DestroyWindow(hWnd)
Case WM_DESTROY
' Окно разрушается, выходим из цикла сообщений
PostQuitMessage(0)
Case Else
' Посылаем все сообщения, которые мы не обрабатываем
' функции по умолчанию
Return DefWindowProc(hWnd, wMsg, wParam, lParam)
End Select
End Function
Компиляция
fbc -s gui "Window.bas" "Window.rc".
Жирным отмечены места, которые были изменены по сравнению с предыдущей программой (Window.bas). Из 120 строк кода новыми оказались всего 20, а сама программа, с точки зрения пользователя, стала намного сложнее. Таким образом выглядит программирование под Windows на FreeBASIC'е — берётся одна написанная раз и навсегда шаблонная программа, модифицируются ресурсы и пишутся обработчики для различных событий меню и диалогов. Фактически всё программирование оказывается сосредоточенным именно в этих процедурах-обработчиках.
Меню — один из краеугольных камней идеологии Win32 (Windows и ReactOS). Похожие друг на друга меню разрешают пользоваться абсолютно незнакомыми программами, не читая инструкций, и узнавать об из возможностях путём просмотра содержания различных пунктов меню. Попробуем добавить меню и в нашу программу Window.bas.
Но перед тем как перейти к программе демонстрации меню, изучим основные концепции Win32, связанные с меню.
Концепция меню
При создании меню для вашей программы нужно сгруппировать команды, выполняющие однотипные действия. Более того, следует присвоить имена этим группам, которые хорошо знакомы пользователям. Тогда, даже если пользователи впервые работают с вашей программой, они легко разыщут требуемую команду или, по крайней мере, будут знать, где её искать. Ниже приведён список некоторых стандартных названий меню, которые вы можете встретить практически в любой программе, написанной для Windows или ReactOS.
File (Файл). В данную группу помещают все команды, которые работают с файлами. Обычно в этом меню находятся такие команды как New (Создать), Open (Открыть), Close (Закрыть), Save (Сохранить), Save As (Сохранить как) и Print (Печать). Если программа предназначена для активной работы с файлами, в данное меню помещается также список нескольких последних файлов, к которым было обращение. Как правило, самой последней командой данного меню является Exit (Выход).
Edit (Правка). В данную группу помещают команды, предназначенные для редактирования объектов и текста, а также для работы с буфером обмена: Undo (Отменить), Cut (Вырезать), Copy (Копировать), Paste (Вставить), Clear (Очистить), Find (Найти) и Replace (Заменить).
View (Вид). В данную группу меню помещают команды, предназначенные для изменения режимов просмотра документа. Например, в программе текстового процессора OpenOffice Writer в этом меню находятся команды для перехода из обычного режима редактирования (предназначенного для набора текста) в режим разметки страницы, в котором выполняется вёрстка макета. Кроме того, в описываемое меню помещается команда изменения масштаба документа.
Tools (Сервис). В данную группу помещаются команды для запуска даполнительных утилит и программ настройки. Например, в программе текстового процессора в этом меню находятся команды для проверки правописания и грамматики.
Window (Окно). Данная группа меню, как правило, включается в те приложения, которые поддерживают многодокументный интерфейс (MDI). MDI-программы, такие как OpenOffice Writer или Calc, позволяют одновременно работать с несколькими документами. Кроме того, меню Window позволяет в одном месте хранить список открытых документов и быстро переключаться между ними.
Help (Справка). В данное меню включаются команды вызова справочной системы. Обычно в нём можно встретить пункты для вызова
оглавления справочной системы (команда Help Index), поиска нужной темы в справочнике (команда Search), а также вывода информации о программе (команда About), её авторах и правах собственности.
Клавиши быстрого доступа
Клавиши быстрого доступа позволяют перемещаться по системе меню без применения мыши. Если в названии меню предусмотрена клавиша быстрого доступа, то в названии меню она будет подчёркнута (например, буква F в меню File). Для создания клавиши достаточно поместить символ амперсенда (&) перед соответствующей буквой в тексте меню. (Если же нужно, чтобы в названии меню отображался символ &, то введите его дважды - &&.) Старайтесь там, где это возможно, назначать в качестве клавиши быстрого доступа первую букву в названии меню, поскольку именно её чаще всего ожидают увидеть пользователи. В то же время, не стоит использовать первую букву в том случае, если она уже назначена для другого элемента меню.
Вы можете назначить часто используемым командам программы специальные сочетания клавиш ("горячие" клавиши, или акселераторы), дабы часто не обращаться к меню для запуска нужной команды. "Грячие" клавиши позволяют запустить команду после нажатия одной (например, <Delete>) или двух (таких как <Ctrl+S>) клавиш клавиатуры. Правильно назначенные клавиатурные эквиваленты ещё больше ускоряют работу пользователя.
File->New Ctrl+N Создать новый документ
File->Open Ctrl+O Открыть новый документ
File->Save Ctrl+S Сохранить документ
File->Print Ctrl+P Распечатать документ
Edit->Cut Ctrl+X Вырезать
Edit->Copy Ctrl+C Копировать
Edit->Paste Ctrl+V Вставить
Edit->Undo Ctrl+Z Отменить
Edit->Find Ctrl+F Найти
Создание меню
Первое, что нам нужно получить, - это само меню. Его, также как значки, диалоги и другую информацию (вплоть до версии программы), записывают в файлы ресурсов. Файл ресурсов имеет расширение *.RC для текстового файла или *.RES для бинарного файла, созданного специальным компилятором ресурсов (RC, BRCC32, WRC). И те, и другие файлы ресурсов можно редактировать особыми программами, сводящими в дистрибутив C/C++, или с помощью других средств разработки для Windows, но мы не будем создавать слишком сложное меню и напишем RC-файл вручную, например, так:
- Код:
// window.rc
// Файл ресурсов для программы Window.bas
// Идентификаторы сообщений от пунктов меню
#define IDM_NEW 1
#define IDM_OPEN 2
#define IDM_SAVE 3
#define IDM_SAVEAS 4
#define IDM_EXIT 5
#define IDM_ABOUT 6
#define IDM_UNDO 7
#define IDM_CUT 8
#define IDM_COPY 9
#define IDM_PASTE 10
#define IDM_CLEAR 11
#define IDM_SELECTALL 12
// Идентификаторы основных ресурсов
#define ID_MENU 13 // Наше меню
#define ID_ACCEL 14 // "Горячие" клавиши (акселераторы)
// Основное меню
ID_MENU MENU {
POPUP "&File" {
MENUITEM "&New\tCtrl+N", IDM_NEW
MENUITEM "&Open...\tCtrl+O", IDM_OPEN
MENUITEM "&Save\tCtrl+S", IDM_SAVE
MENUITEM "Save &As...\tCtrl+Shift+S", IDM_SAVEAS
MENUITEM SEPARATOR // Под словом SEPARATOR понимается тонкая разделительная линия между пунктами меню
MENUITEM "E&xit\tCtrl+Q", IDM_EXIT
}
POPUP "&Edit" {
MENUITEM "&Undo\tCtrl+Z", IDM_UNDO
MENUITEM SEPARATOR
MENUITEM "Cu&t\tCtrl+X", IDM_CUT
MENUITEM "&Copy\tCtrl+c", IDM_COPY
MENUITEM "&Paste\tCtrl+V", IDM_PASTE
MENUITEM "&Delete\tDel", IDM_CLEAR
MENUITEM SEPARATOR
MENUITEM "Select &All\tCtrl+A", IDM_SELECTALL
}
POPUP "&Help" {
MENUITEM "About", IDM_ABOUT
}
}
// Комбинации клавиш
ID_ACCEL ACCELERATORS {
"N", IDM_NEW, CONTROL, VIRTKEY
"O", IDM_OPEN, CONTROL, VIRTKEY
"S", IDM_SAVE, CONTROL, VIRTKEY
"S", IDM_SAVEAS, CONTROL, SHIFT, VIRTKEY
"Q", IDM_EXIT, CONTROL, VIRTKEY
"Z", IDM_UNDO, CONTROL, VIRTKEY
"A", IDM_SELECTALL, CONTROL, VIRTKEY
}
Полный код программы Window.bas с меню
#Include once "windows.bi"
' Функция, в которой будет происходить
' цикл обработки сообщений
Declare Function WndProc(ByVal hWnd As HWND, ByVal wMsg As UINT, ByVal wParam As WPARAM, ByVal lParam As LPARAM) As LRESULT
''
'' Program Start
''
Dim hInst As HINSTANCE ' Идентификатор нашего процесса
Dim wMsg As MSG ' Сообщения, принимаемые от окна
Dim wc As WNDCLASS ' Структура нашего класса окна
Dim hWnd As HWND ' Идентификатор окна
Dim hAccel As HACCEL ' Идентификатор акселератора
' Получаем идентификатор нашего процесса
hInst = GetModuleHandle(0)
/' Функция Cast приводит выражение из правой части
к типу, указанному в левой части так что запись типа
Cast(ZString Ptr, 14)
получает нужный нам указатель на идентификатор акселератора
'/
' Загружаем "Горячие" клавиши (акселераторы)
hAccel = LoadAccelerators(hInst, Cast(ZString Ptr, 14))
' Создаём структуру класса окна
With wc
' Стиль прорисовки окна
.style = CS_HREDRAW Or CS_VREDRAW
' Адрес функции обработки сообщения, посылаемых окну
.lpfnWndProc = @WndProc
' Дополнительные данные
.cbClsExtra = 0
.cbWndExtra = 0
' Идентификатор процесса, создающего класс окна
.hInstance = hInst
' Значок окна
.hIcon = LoadIcon(0, IDI_APPLICATION)
' Курсор по умолчанию
.hCursor = LoadCursor(0, IDC_ARROW)
' Кисть по умолчанию для отрисовки фона окна
.hbrBackground = Cast(HBRUSH, COLOR_BTNFACE + 1)
' Имя нашего меню из ресурсов
.lpszMenuName = Cast(ZString Ptr, 13)
' Адрес строки с именем класса окна
.lpszClassName = @"FBWindow"
End With
' Регистрируем класс окна
RegisterClass(@wc)
' Создаём окно с именем зарегистрированного класса
hWnd = CreateWindow(@"FBWindow", _ /' Адрес строки с именем класса окна '/
"Пример простого окна с меню", _ /' Заголовок нашего окна '/
WS_OVERLAPPEDWINDOW, _ /' Стиль окна '/
CW_USEDEFAULT, _ /' X-позиция на экране, используем по умолчанию '/
CW_USEDEFAULT, _ /' Y-позиция на экране, используем по умолчанию '/
640, _ /' Ширина нашего окна '/
480, _ /' Высота нашего окна '/
0, _ /' Идентификатор родительского окна, используется если создаваемое окно является дочерним '/
0, _ /' Идентификатор меню из ресурсов программы,
так как мы определили меню в классе окна
то оставляем здесь 0 '/
hInst, _ /' Идентификатор процесса, создающего окно '/
0) /' Дополнительные данные, у нас их нет '/
' Показываем окно
ShowWindow(hWnd, SW_NORMAL)
' Обновляем содержимое окна
' При этом окну посылается сообщение WM_PAINT
UpdateWindow(hWnd)
' Цикл обработки сообщений от окна
Do While GetMessage(@wMsg, 0, 0, 0) <> 0
' Добавляем проверку на нажатие горячих клавиш
If TranslateAccelerator(hWnd, hAccel, @wMsg) = 0 Then
TranslateMessage(@wMsg)
DispatchMessage(@wMsg)
End If
Loop
''
'' Program End
''
'
' Функция для обработки сообщений от окна
'
Function WndProc(ByVal hWnd As HWND, _
ByVal wMsg As UINT, _
ByVal wParam As WPARAM, _
ByVal lParam As LPARAM) As LRESULT
Select Case(wMsg)
Case WM_CREATE
' Здесь должна происходить инициализация
Case WM_COMMAND
' Сообщения от меню
Select Case HiWord(wParam)
Case BN_CLICKED, 1
Select Case LoWord(wParam)
Case 1
' Пункт меню New (создать новый документ)
Case 2
' Пункт меню Open (открыть)
Case 3
' Пункт меню Save (сохранить)
Case 4
' Пункт меню SaveAs (сохранить под другим именем)
Case 5
' Пункт меню Exit (закрыть программу)
' Уничтожаем окно
DestroyWindow(hWnd)
Case 6
' Пункт меню About (о программе)
Case 7
' Пункт меню Undo (отменить)
Case 8
' Пункт меню Cut (вырезать в буфер обмена)
Case 9
' Пункт меню Copy (копировать в буфер обмена)
Case 10
' Пункт меню Paste (вставить из буфера обмена)
Case 11
' Пункт меню Clear (очистить текстовое поле)
Case 12
' Пункт меню SelectAll (выделить весь текст)
End Select
End Select
Case WM_CLOSE
' Сообщение о закрытии окна
' Окно нужно уничтожить
DestroyWindow(hWnd)
Case WM_DESTROY
' Окно разрушается, выходим из цикла сообщений
PostQuitMessage(0)
Case Else
' Посылаем все сообщения, которые мы не обрабатываем
' функции по умолчанию
Return DefWindowProc(hWnd, wMsg, wParam, lParam)
End Select
End Function
Компиляция
fbc -s gui "Window.bas" "Window.rc".
Жирным отмечены места, которые были изменены по сравнению с предыдущей программой (Window.bas). Из 120 строк кода новыми оказались всего 20, а сама программа, с точки зрения пользователя, стала намного сложнее. Таким образом выглядит программирование под Windows на FreeBASIC'е — берётся одна написанная раз и навсегда шаблонная программа, модифицируются ресурсы и пишутся обработчики для различных событий меню и диалогов. Фактически всё программирование оказывается сосредоточенным именно в этих процедурах-обработчиках.
Последний раз редактировалось: zamabuvaraeu (Чт Окт 09, 2008 9:43 am), всего редактировалось 2 раз(а)
Re: Платформа Win32 - Меню и акселераторы
Ага! Вот и меню. Значит ты пошел к ресурсам. Меня же больше интересовал чистый код.
Вот пример из examples, но с русскими словечками.
Вот пример из examples, но с русскими словечками.
- Код:
' демонстрация работы с меню
#include once "windows.bi"
' внутренняя структура
type TMENU
hnd as HMENU
end type
type TMENUITEM
title as string
id as integer
end type
' пункты меню
const MENUID_BASE = 100
enum MENUID_ENUM
MENUID_FILE_NEW = MENUID_BASE
MENUID_FILE_OPEN
MENUID_FILE_EXIT
MENUID_PROJECT_NEW
MENUID_PROJECT_OPEN
MENUID_FILE_CLOSE
MENUID_EDIT_UNDO
MENUID_EDIT_REDO
MENUID_EDIT_CUT
MENUID_EDIT_COPY
MENUID_SEARCH_FIND
MENUID_SEARCH_FINDNEXT
MENUID_SEARCH_FINDPREV
MENUID_SEARCH_REPLACE
end enum
const MAXMENUS = 10
const MAXMENUITEMS = 50
declare sub init_menus( byval hWnd as HWND )
declare function WinMain ( byval hInstance as HINSTANCE, _
byval hPrevInstance as HINSTANCE, _
byref szCmdLine as string, _
byval iCmdShow as integer ) as integer
' глобальные
dim shared submenuTB(0 to MAXMENUS) as TMENU
dim shared menuitemTB(0 to MAXMENUITEMS-1) as TMENUITEM
' точка входа
end WinMain( GetModuleHandle( null ), null, Command, SW_NORMAL )
'' name: WndProc
' desc: обработка сообщений окна
function WndProc ( byval hWnd as HWND, _
byval message as UINT, _
byval wParam as WPARAM, _
byval lParam as LPARAM ) as LRESULT
dim rct as RECT
dim pnt as PAINTSTRUCT
dim hDC as HDC
static lastmenuid as integer
dim wmId as integer, wmEvent as integer
dim menu as HMENU
function = 0
' обработка сообщений
select case ( message )
'' окно создано
case WM_CREATE
' создание и отображение меню
init_menus( hWnd )
exit function
' выбран пункт меню
case WM_COMMAND
wmId = loword( wParam )
wmEvent = hiword( wParam )
menu = GetMenu( hWnd )
' разбираем, какой пункт меню был выбран
select case wmId
'' выход
case MENUID_FILE_EXIT
PostMessage( hWnd, WM_CLOSE, 0, 0 )
exit function
end select
' сохраняем последний id пункта меню
lastmenuid = wmId
' вызовите перекрашивание так меню id, и название будет оттянуто
GetClientRect( hWnd, @rct )
InvalidateRect( hWnd, @rct, TRUE )
' окно перекрашиваеться
case WM_PAINT
hDC = BeginPaint( hWnd, @pnt )
GetClientRect( hWnd, @rct )
if( lastmenuid <> 0 ) then
DrawText( hDC, _
"Last menu selected: id(" & lastmenuid & ") title(" & menuitemTB(lastmenuid-MENUID_BASE).title & ")", _
-1, _
@rct, _
DT_SINGLELINE or DT_CENTER or DT_VCENTER )
end if
EndPaint( hWnd, @pnt )
exit function
case WM_KEYDOWN
if( lobyte( wParam ) = 27 ) then
PostMessage( hWnd, WM_CLOSE, 0, 0 )
end if
' окно было закрыто
case WM_DESTROY
PostQuitMessage( 0 )
exit function
end select
' это сообщение нас не касаеться, посылаеться обработчику
function = DefWindowProc( hWnd, message, wParam, lParam )
end function
' name: WinMain
' desc: точка входа win2 gui программы
function WinMain ( byval hInstance as HINSTANCE, _
byval hPrevInstance as HINSTANCE, _
byref szCmdLine as string, _
byval iCmdShow as integer ) as integer
dim wMsg as MSG
dim wcls as WNDCLASS
dim appName as string
dim hWnd as HWND
function = 0
' устанавливаем класс окна
appName = "Menu Test"
with wcls
.style = CS_HREDRAW or CS_VREDRAW
.lpfnWndProc = @WndProc
.cbClsExtra = 0
.cbWndExtra = 0
.hInstance = hInstance
.hIcon = LoadIcon( null, IDI_APPLICATION )
.hCursor = LoadCursor( null, IDC_ARROW )
.hbrBackground = GetStockObject( WHITE_BRUSH )
.lpszMenuName = null
.lpszClassName = strptr( appName )
end with
' регистрируем окно
if ( RegisterClass( @wcls ) = false ) then
MessageBox( null, "Failed to register the window class", appName, MB_ICONERROR )
exit function
end if
' создаём и выводим окно
hWnd = CreateWindowEx( 0, _
appName, _
"Menu test", _
WS_OVERLAPPEDWINDOW, _
CW_USEDEFAULT, _
CW_USEDEFAULT, _
CW_USEDEFAULT, _
CW_USEDEFAULT, _
null, _
null, _
hInstance, _
null )
ShowWindow( hWnd, iCmdShow )
UpdateWindow( hWnd )
' обработка сообщений окна
while( GetMessage( @wMsg, null, 0, 0 ) <> false )
TranslateMessage( @wMsg )
DispatchMessage( @wMsg )
wend
' программа завершаеться
function = wMsg.wParam
end function
sub menu_insert( byval hmenu as HMENU, byval submenu as integer, byref title as string, byval flags as integer = 0 )
with submenuTB(submenu)
.hnd = CreatePopupMenu( )
InsertMenu( hmenu, submenu, MF_BYPOSITION Or MF_POPUP Or MF_STRING or flags, cuint( .hnd ), title )
end with
end sub
sub menu_append( byval submenu as integer, byval id as integer, byref title as string, byval flags as integer = 0 )
with menuitemTB(id-MENUID_BASE)
.id = id
.title = title
AppendMenu( submenuTB(submenu).hnd, MF_STRING or flags, id, title )
end with
end sub
sub menu_separator( byval submenu as integer )
AppendMenu( submenuTB(submenu).hnd, MF_SEPARATOR, 0, NULL )
end sub
sub init_menus( byval hWnd as HWND )
dim menu as HMENU
menu = CreateMenu( )
' файл
menu_insert( menu, 0, "&файл" )
menu_append( 0, MENUID_FILE_NEW, "&новый" )
menu_append( 0, MENUID_FILE_OPEN, "&открыть..." )
menu_insert( submenuTB(0).hnd, 3, "&Project" )
menu_append( 3, MENUID_PROJECT_NEW, "&новый" )
menu_append( 3, MENUID_PROJECT_OPEN, "&открыть..." )
menu_append( 0, MENUID_FILE_CLOSE, "&закрыть" )
menu_separator( 0 )
menu_append( 0, MENUID_FILE_EXIT, "в&ыход" )
' правка
menu_insert( menu, 1, "&правка" )
menu_append( 1, MENUID_EDIT_UNDO, "&отменить" )
menu_append( 1, MENUID_EDIT_REDO, "&заного" )
menu_separator( 1 )
menu_append( 1, MENUID_EDIT_CUT, "в&ырезать" )
menu_append( 1, MENUID_EDIT_COPY, "&копировать" )
' найти
menu_insert( menu, 2, "&найти" )
menu_append( 2, MENUID_SEARCH_FIND, "&найти" )
menu_append( 2, MENUID_SEARCH_FINDNEXT, "найти &следующее" )
menu_append( 2, MENUID_SEARCH_FINDPREV, "найти &предыдущее" )
menu_append( 2, MENUID_SEARCH_REPLACE, "&заменить", MF_MENUBARBREAK )
SetMenu( hWnd, menu )
DrawMenuBar( hWnd )
end sub
Re: Платформа Win32 - Меню и акселераторы
zamabuvaraeu, огромное спасибо!!! вот бы все так про винды писали!!! теперь будем ждать про диалоги, хотя я их умею делать, но все же.
респект.
респект.
electrik- Сообщения : 391
Дата регистрации : 2008-09-02
Возраст : 43
Откуда : галактика Млечный путь, система Солнечная, планета Земля, страна россия, город Санкт Петербург
Re: Платформа Win32 - Меню и акселераторы
eric, я тебя уважаю зато, что ты не идеш по короткому пути, пытаясь писать менюшки, окошки менуя пресурсы, я сам люблю маленький и быстрый код, но в данном случае лучше пользовать ресурсы, расскажу почему.
меню написанное при помощи твоего способа, является прямым обращением к винде, и не как не входит в таблицу ресурсов, тоесть, в программах типа: "resource hacker", "exescope" менюшки не видятся. соответственно, наступает проблема локализаций на другие языки. конечно же можно все запехать в специальный *.lang файл, но это дополнительный код. соответственно, выигрыша по скорости нет. прелесть ресурсов в том, что прямо в бинарнике, специальными программами можно менять размеры окон, удалять или вставлять картинки, менять свойство кнопок, текст на кнопках и т.д. как-то я захотел русифицировать программу, а мне фиг. какой-то диалог, типа о программе и все. весь интерфейс программы, состоял из стандартных виндовых окон, но в ресурсах не менюшек, ни важных диалоговых окон небыло. короче, если вы хотите все скрыть, пишите на прямую, а мне, ресурсы пока по душе.
меню написанное при помощи твоего способа, является прямым обращением к винде, и не как не входит в таблицу ресурсов, тоесть, в программах типа: "resource hacker", "exescope" менюшки не видятся. соответственно, наступает проблема локализаций на другие языки. конечно же можно все запехать в специальный *.lang файл, но это дополнительный код. соответственно, выигрыша по скорости нет. прелесть ресурсов в том, что прямо в бинарнике, специальными программами можно менять размеры окон, удалять или вставлять картинки, менять свойство кнопок, текст на кнопках и т.д. как-то я захотел русифицировать программу, а мне фиг. какой-то диалог, типа о программе и все. весь интерфейс программы, состоял из стандартных виндовых окон, но в ресурсах не менюшек, ни важных диалоговых окон небыло. короче, если вы хотите все скрыть, пишите на прямую, а мне, ресурсы пока по душе.
electrik- Сообщения : 391
Дата регистрации : 2008-09-02
Возраст : 43
Откуда : галактика Млечный путь, система Солнечная, планета Земля, страна россия, город Санкт Петербург
Re: Платформа Win32 - Меню и акселераторы
Я так понимаю функция CreateMenu()
http://www.firststeps.ru/mfc/winapi/menu/r.php?62
Она может вызываться только после создания окна?
Или её всё же можно вызвать, до создания?
Я бы хотел поиметь дескриптор менюшки, ещё на стадии инициализации формы.
http://www.firststeps.ru/mfc/winapi/menu/r.php?62
Она может вызываться только после создания окна?
Или её всё же можно вызвать, до создания?
Я бы хотел поиметь дескриптор менюшки, ещё на стадии инициализации формы.
Re: Платформа Win32 - Меню и акселераторы
Вот я смотрю, здесь
И чего-то не пойму. LoWord(wParam) возвращает id пункта меню.
Но ведь событие WM_COMMAND, происходит и для нажатия кнопок?
Только уже проверяеться HiWord(wParam).
Так вот вопрос: как отличить команду меню, от команды кнопки? Чему будет равна HiWord(wParam) для меню?
Case BN_CLICKED, 1 это что обозначает?
- Код:
Case WM_COMMAND
' Сообщения от меню
Select Case HiWord(wParam)
Case BN_CLICKED, 1
Select Case LoWord(wParam)
Case 1
И чего-то не пойму. LoWord(wParam) возвращает id пункта меню.
Но ведь событие WM_COMMAND, происходит и для нажатия кнопок?
Только уже проверяеться HiWord(wParam).
Так вот вопрос: как отличить команду меню, от команды кнопки? Чему будет равна HiWord(wParam) для меню?
Case BN_CLICKED, 1 это что обозначает?
Re: Платформа Win32 - Меню и акселераторы
Вот что я только что прочитал.
Проверил. и моя Менюшка работает. Событие отрабатывает.
Обратите внимание, что меню тоже шлёт сообщение WM_COMMAND, чтобы уведомить окно о своем состоянии. Как мы можем провести различие между сообщениями WM_COMMAND,
исходящими от меню и контролов? Вот ответ:
Нижнее слово wParam Верхнее слово wParam lParam ID меню 0 0 ID контрола Код уведомления Хэндл дочернего окна
Вы можете видеть, что вы должны проверить lParam. Если он равен нулю, текущее сообщение WM_COMMAND было послано меню. Вы не можете использовать wParam,
чтобы различать меню и контрол, так как ID меню и ID контрола могут быть идентичными и код уведомления должен быть равен нулю.
Проверил. и моя Менюшка работает. Событие отрабатывает.
Страница 1 из 1
Права доступа к этому форуму:
Вы не можете отвечать на сообщения