Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> window subclassing, WinAPI 
V
    Опции темы
Belous
Дата 10.3.2016, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 8.11.2015

Репутация: нет
Всего: нет



Как сделать переход по элементам управления (э.у.) при нажатии <Tab>

В книжке Ч.Петзолд "Программирование для Windows 95" написано, что для этого нужно "введение новой оконной процедуры" (window subclassing). В тестовом примере я сделал почти так, как написано в книжке, за исключением:
1) у меня вместо 3 полос прокрутки - 3 кнопки;
2) у меня э.у. не в главном окне а в модальном. И код вынесен в модуль "Options.cpp", поэтому пришлось сделать 
static WNDPROC foptions[3]; иначе без волшебного слова static программа не компилируется.

В итоге программа компилируется, а потом при выполнении вываливается с ошибкой (см рисунок)

Вопрос как же сделать этот субклассинг?

Добавлено через 42 секунды
Код

// Options.cpp

#include "Options.h"

void Options::CreateDlg(HINSTANCE hinstance)
{
    InitCommonControls();
    WNDCLASSEX w;
    w.cbSize = sizeof(w);
    w.cbClsExtra = 0;
    w.cbWndExtra = 0;
    w.hbrBackground    = (HBRUSH) (COLOR_BTNFACE + 1);
    w.hCursor = LoadCursor(NULL, IDC_ARROW);
    w.hIcon = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_ICON_D));
    w.hIconSm = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_ICON_D));
    w.hInstance = hinstance;
    w.lpfnWndProc = WndProcOptions;
    w.lpszClassName = STR_OPTIONS;
    w.lpszMenuName = NULL;
    w.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClassEx(&w);
}

void Options::ShowDlg(HWND hwnd, HINSTANCE hinstance)
{
    HWND hdlg;
    POINT point;
    RECT rect;
    DWORD dwStyle;
    EnableWindow(hwnd, FALSE);
    dwStyle = WS_POPUPWINDOW | WS_CAPTION;
    hdlg = CreateWindow(STR_OPTIONS, " Options", dwStyle, 0, 0, 0, 0, hwnd, NULL, hinstance, NULL);
    GetWindowRect(hwnd, &rect);
    point.x = (long) (rect.left + (rect.right - rect.left - INT_OPTIONS_WIDTH) / 2);
    point.y = (long) (rect.top + (rect.bottom - rect.top - INT_OPTIONS_HEIGHT) / 2);
    MoveWindow(hdlg, point.x, point.y, INT_OPTIONS_WIDTH, INT_OPTIONS_HEIGHT, FALSE);
    ShowWindow(hdlg, SW_SHOW);
    //
    dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON;
    hoptionsbutton[0] = CreateWindowEx(0, WC_BUTTON, NULL, dwStyle, 232, 365, 75, 23, hdlg, (HMENU) 1001, hinstance, NULL); // Apply
    ShowWindow(hoptionsbutton[0], SW_SHOW);
    hoptionsbutton[1] = CreateWindowEx(0, WC_BUTTON, NULL, dwStyle, 315, 365, 75, 23, hdlg, (HMENU) 1002, hinstance, NULL); // OK
    ShowWindow(hoptionsbutton[1], SW_SHOW);
    hoptionsbutton[2] = CreateWindowEx(0, WC_BUTTON, NULL, dwStyle, 398, 365, 75, 23, hdlg, (HMENU) 1003, hinstance, NULL); // Cancel
    ShowWindow(hoptionsbutton[2], SW_SHOW);
    foptions[0] = (WNDPROC) SetWindowLong(hoptionsbutton[0], GWL_WNDPROC, (LONG) WndProcOptionsButton);
    foptions[1] = (WNDPROC) SetWindowLong(hoptionsbutton[1], GWL_WNDPROC, (LONG) WndProcOptionsButton);
    foptions[2] = (WNDPROC) SetWindowLong(hoptionsbutton[2], GWL_WNDPROC, (LONG) WndProcOptionsButton);
}

Options::Options()
{
}

Options::~Options()
{
}

LRESULT CALLBACK WndProcOptions(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
    HWND hparent;
    int i;
    hparent = GetParent(hwnd);
    switch (message)
    {
    case WM_KEYDOWN:
        switch (LOWORD(wparam))
        {
        case VK_ESCAPE:
            SendMessage(hwnd, WM_CLOSE, NULL, NULL);
            break;
        default:
            break;
        }
        return 0;
    case WM_COMMAND:
        i = GetWindowLong((HWND) lparam, GWL_ID);
        switch (LOWORD(wparam))
        {
        case 1001:
            MessageBox(hwnd, "WM_COMMAND 1001", "Message", MB_OK);
            break;
        case 1002:
            MessageBox(hwnd, "WM_COMMAND 1002", "Message", MB_OK);
            break;
        case 1003:
            MessageBox(hwnd, "WM_COMMAND 1003", "Message", MB_OK);
            break;
        default:
            break;
        }
        return 0;
    case WM_CLOSE:
        EnableWindow(hparent, TRUE);
        SetFocus(hparent);
        BringWindowToTop(hparent);
        DestroyWindow(hwnd);
        return 0;
    }
    return DefWindowProc(hwnd, message, wparam, lparam);
}

LRESULT CALLBACK WndProcOptionsButton(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
    int i = GetWindowLong(hwnd, GWL_ID);
    switch (message)
    {
    case WM_KEYDOWN:
        if (wparam == VK_TAB) SetFocus(hoptionsbutton[(i+(GetKeyState(VK_SHIFT) < 0 ? 2 : 1)) % 3]);
        break;
    case WM_SETFOCUS:
        ifocus = i;
        break;
    }
    return CallWindowProc(foptions[i], hwnd, message, wparam, lparam);
}


Добавлено через 1 минуту и 38 секунд
Код

// Options.h

#include <windows.h>
#include <commctrl.h>
#include "resource.h"

#pragma comment (lib, "comctl32.lib")

#define STR_OPTIONS                "ClassOptions"
#define INT_OPTIONS_WIDTH        485
#define INT_OPTIONS_HEIGHT        420

static HICON hiconoptions;
static HWND hoptionsbutton[3];
static WNDPROC foptions[3];
static int ifocus;

class Options
{
public:
    void CreateDlg(HINSTANCE hinstance);
    void ShowDlg(HWND hwnd, HINSTANCE hinstance);
    Options();
    ~Options();
};

LRESULT CALLBACK WndProcOptions(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
LRESULT CALLBACK WndProcOptionsButton(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);


Присоединённый файл ( Кол-во скачиваний: 6 )
Присоединённый файл  Pic_003.GIF 16,97 Kb
PM MAIL   Вверх
Belous
Дата 10.3.2016, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 8.11.2015

Репутация: нет
Всего: нет



исходник


Присоединённый файл ( Кол-во скачиваний: 0 )
Присоединённый файл  Test_003.rar 25,46 Kb
PM MAIL   Вверх
feodorv
Дата 10.3.2016, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Цитата(Belous @  10.3.2016,  18:17 Найти цитируемый пост)
В итоге программа компилируется, а потом при выполнении вываливается с ошибкой (см рисунок)

В суть вопроса не влезал. По падению программы: у Вас есть hwnd, зачем Вы в CallWindowProc передаёте foptions[i]?
Цитата(Belous @  10.3.2016,  18:17 Найти цитируемый пост)
    return CallWindowProc(foptions[ i ], hwnd, message, wparam, lparam);
 
И чему равно i? Точно меньше 3? А массив foptions инициализирован к моменту вызова CallWindowProc?


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
GremlinProg
Дата 10.3.2016, 22:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Belous @  10.3.2016,  20:17 Найти цитируемый пост)
GetWindowLong(hwnd, GWL_ID);

это лучше заменить на GetDlgCtrlID, хотя, проблема конечно не в этом
Цитата(Belous @  10.3.2016,  20:17 Найти цитируемый пост)
(HMENU) 1001

а вот это - уже проблема, т.к. вот здесь:
Цитата(Belous @  10.3.2016,  20:17 Найти цитируемый пост)
CallWindowProc(foptions[i], hwnd, message, wparam, lparam);

i равен как раз одному из 1001..1003


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Belous
Дата 11.3.2016, 19:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 8.11.2015

Репутация: нет
Всего: нет



Исправил, все работает. Всем спасибо.

Это сообщение отредактировал(а) Belous - 11.3.2016, 19:20
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.1120 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.