Форум программистов, компьютерный форум CyberForum.ru

WinAPI vs VCL - Привязка к окну каких-либо данных - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 25, средняя оценка - 4.96
John Paramol
Сообщений: n/a
21.06.2012, 11:45     WinAPI vs VCL - Привязка к окну каких-либо данных #1
Привет.

Решил взяться доработать класс, который когда-то делал,
класс окна наподобие TWinControl или TForm из VCL.
Меня интересует, каким образом можно к каждому окну привязать
какую-либо информацию, причем сразу в момент создания.
Точнее, в моем случае, нужно привязать указатель this
того объекта, к которому это окно относится.
Я это делаю так:
Код
SetWindowLong(Handle,GWL_USERDATA,(long)this);
но в VCL это делается по-другому, хотя бы потому, что GetWindowLong(Handle,GWL_USERDATA) формы всегда возвращает 0.
Мне этот способ не подходит, т.к. по событию WM_CREATE/WM_NCCREATE
USERDATA еще не инициализирована, и получить this объекта нельзя.
Кто-нибудь знает другие способы, или тот, который используется в VCL?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.06.2012, 11:45     WinAPI vs VCL - Привязка к окну каких-либо данных
Посмотрите здесь:

C++ две прямые либо паралельны либо совпадают либо не существуют
Сумма каких-либо двух цифр заданного трехзначного натурального числа N равна третьей цифре. C++
Структуры данных. Написать программу, позволяющую определить, есть ли в школе в каких-либо классах однофамильцы C++
C++ Разработать орнамент на основе каких-либо математических кривых и заполнить ими экран
Написать программу, которая по заданным трем числам определяет, является ли сумма каких-либо двух из них положительной C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
arist
0 / 0 / 0
Регистрация: 14.02.2011
Сообщений: 100
21.06.2012, 12:58     WinAPI vs VCL - Привязка к окну каких-либо данных #2
Может я не совсем въехал, но...
Если ты пишешь, что-то типа TForm, зачем к HWND привязывать this?
Я думаю в VCL наоборот, к this привязан HWND, т.е. *this содержит в себе HWND.

P.S.
Бросай BCB. Inprise уже бросила. И я тоже...
John Paramol
Сообщений: n/a
21.06.2012, 17:21     WinAPI vs VCL - Привязка к окну каких-либо данных #3
>>зачем к HWND привязывать this?

В конструкторе класса, после создания окна,
SetWindowLong привязывает this к окну.
Оконная процедура WndProc, находящаяся в моем классе является статической,
она не может обращаться к членам и методам класса непосредственно.
Каждый раз, когда ей обрабатывается сообщение, GetWindowLong достает this,
и через него у меня идет обращение к методам.

PS я не сторонник BCB, но мне нравится мощность VCL. Хотя она чрезмерна.
Данный же класс не будет привязан к конкретной среде разработки
John Paramol
Сообщений: n/a
23.06.2012, 21:40     WinAPI vs VCL - Привязка к окну каких-либо данных #4
Отказался от SetWindowLong.
Просто сделал статическим членом класса вектор, содержащий пары HWND-this;
в конструкторе добавляю пару, в деструкторе удаляю, а в WndProc перебираю все
пары, выбираю нужную и беру this.

Чтобы не ходить вокруг да около, покажу урезанный вариант класса

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <windows.h>
#include <windowsx.h>
#include <typeinfo.h>
#include <vector.h>
 
class __rtti XXWindow
{
  private:
    XXWindow();
    XXWindow(const XXWindow &obj);
  protected:
    typedef struct
    {
      HWND Hwnd;
      LPVOID This;
    } XXHWND2THIS;
    static vector<XXHWND2THIS> HwndTable;
 
    // ...
 
    HINSTANCE hInstance;
    WNDCLASSEX WndClassEx;
    char const *ClassName;
  public:
    HWND Handle;
 
    // ...
 
    XXWindow(HINSTANCE hinstance,DWORD dwExStyle,DWORD dwStyle,HWND parent)
    : hInstance(hinstance),
      Handle(NULL),
      ClassName(typeid(*this).name())
    {
      WndClassEx.cbSize          = sizeof(WNDCLASSEX);
      WndClassEx.style           = CS_HREDRAW | CS_VREDRAW;
      WndClassEx.lpfnWndProc     = WndProc;
      WndClassEx.cbClsExtra      = 0;
      WndClassEx.cbWndExtra      = 0;
      WndClassEx.hInstance       = hInstance;
      WndClassEx.hIcon           = NULL;
      WndClassEx.hCursor         = LoadCursor(NULL, IDC_ARROW);
      WndClassEx.hbrBackground   = (HBRUSH)COLOR_BTNSHADOW;
      WndClassEx.lpszMenuName    = NULL;
      WndClassEx.lpszClassName   = ClassName;
      WndClassEx.hIconSm     = NULL;
      RegisterClassEx(&WndClassEx);
      Handle = CreateWindowEx(dwExStyle, ClassName, ClassName, dwStyle,
            CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, parent, NULL, hInstance, NULL);
      if(Handle == NULL) { Beep(1000,100); return; }
      XXHWND2THIS tbl = {(HWND)Handle,(LPVOID)this};
      HwndTable.push_back(tbl); // добавляю пару в вектор
    }
    ~XXWindow()
    {
      UINT size = HwndTable.size();
      for(UINT i=0; i<size; ++i)
        if(HwndTable[i].Hwnd == Handle)
          HwndTable.erase(HwndTable.begin()+i); // удаляю пару
    }
    static LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
    {
      static BOOL dispatched;
      static LRESULT res;
      static XXWindow *ptr;
      ptr = NULL;
      UINT size = HwndTable.size();
      for(UINT i=0; i<size; ++i)
        if(HwndTable[i].Hwnd==hwnd)
          ptr=(XXWindow*)HwndTable[i].This; // достаю this
      if(ptr==NULL) return DefWindowProc(hwnd, Message, wParam, lParam);
      dispatched = FALSE;
      res = ptr->Dispatch(hwnd, Message, wParam, lParam, dispatched);
      if(dispatched) return res;
      switch(Message)
      {
        HANDLE_MSG(hwnd, WM_COMPACTING,         ptr->Event_OnCompacting);
        HANDLE_MSG(hwnd, WM_WININICHANGE,   ptr->Event_OnWinIniChange);
        HANDLE_MSG(hwnd, WM_SYSCOLORCHANGE, ptr->Event_OnSysColorChange);
        // ...
        // дальше продолжается длинный-длинный список хендлеров
        // ...
      }
      dispatched = TRUE;
      return ptr->Dispatch(hwnd,Message,wParam,lParam,dispatched);
    }
    virtual LRESULT Dispatch(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam, BOOL &Dispatched)
    {
      if(Dispatched) return DefWindowProc( hwnd, Message, wParam, lParam );
      return 0;
    }
    //-----------------------------------------------------------
    // Message handlers.
    //-----------------------------------------------------------
    virtual void Event_OnCompacting(HWND hwnd, UINT compactRatio)
    {
        DefWindowProc( hwnd, WM_COMPACTING, (WPARAM)compactRatio, (LPARAM)0L );
    }
    virtual void Event_OnWinIniChange(HWND hwnd, LPCTSTR lpszSectionName)
    {
        DefWindowProc( hwnd, WM_WININICHANGE, (WPARAM)0U, (LPARAM)lp
vagabond
0 / 0 / 0
Регистрация: 13.11.2011
Сообщений: 6
24.06.2012, 09:53     WinAPI vs VCL - Привязка к окну каких-либо данных #5
Привет.
Посмотри здесь.
http://www.softcraft.ru/winapi.shtml
Удачи.
John Paramol
Сообщений: n/a
24.06.2012, 23:59     WinAPI vs VCL - Привязка к окну каких-либо данных #6
vagabond, вон туда меня уже посылали.

Есть там пример generic, в нем не решена моя проблема.
Этой проблемы там просто нет, т.к. те сообщения не обрабатываются.
И вообще по-моему не предусмотрено наследование с последующей спецификацией классов.
К тому же используется SetWindowLong(...,GWL_USERDATA,...),
от чего я отказался в пользу возможности другого применения USERDATA.
Сдается мне, там все не в лучшую сторону наворочено.
Зачем нужна классовая оболочка, если нет модульности?
Множество мелких классов, образующих столь затейливую, но неуклюжую систему -
не дружественный подход в программировании.

А вообще, спасибо за содействие.

... Cthulhu Fatang?
arist
0 / 0 / 0
Регистрация: 14.02.2011
Сообщений: 100
25.06.2012, 09:38     WinAPI vs VCL - Привязка к окну каких-либо данных #7
Самому стало интересно. Порылся в недрах MFC. Вот что нарыл...

На счёт карты соответствий HWND-this там вроде как сделано аналогично как у тебя, но для потока в целом, а не для каждого класса окна.

На счёт WM_CREATE и подобных. Возможно метод OnCreate вызывается искусственно, после CreateWindow, но есть подозрение, что здесь используются хуки.

...А нет вот смотри MSDN:
CreateWindowEx Function
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
HWND CreateWindowEx(DWORD dwExStyle,
    LPCTSTR lpClassName,
    LPCTSTR lpWindowName,
    DWORD dwStyle,
    int x,
    int y,
    int nWidth,
    int nHeight,
    HWND hWndParent,
    HMENU hMenu,
    HINSTANCE hInstance,
    LPVOID lpParam
);
...
lpParam
[in] Pointer to a value to be passed to the window through the CREATESTRUCT structure passed in the lpParam parameter the WM_CREATE message...
...

Т.е. в твоём случае в конструкторе в вызове CreateWindowEx в lpParam передаёшь this.
arist
0 / 0 / 0
Регистрация: 14.02.2011
Сообщений: 100
25.06.2012, 09:44     WinAPI vs VCL - Привязка к окну каких-либо данных #8
Обрати внимание lParam - это Pointer to a value.
т.е. ты должен передать (void *)&this.
CoolGun
1 / 1 / 0
Регистрация: 18.07.2010
Сообщений: 36
26.06.2012, 16:21     WinAPI vs VCL - Привязка к окну каких-либо данных #9
SetProp
arist
0 / 0 / 0
Регистрация: 14.02.2011
Сообщений: 100
26.06.2012, 17:43     WinAPI vs VCL - Привязка к окну каких-либо данных #10
SetProp в данном случае не подходит, так как требует HWND...
John Paramol
Сообщений: n/a
27.06.2012, 23:00     WinAPI vs VCL - Привязка к окну каких-либо данных #11
Видели прикол? У меня работает следующий код:
if(ptr==NULL) ptr->Method();
Работает, если Method не виртуальный и не обращается к членам и методам класса.
Ясно, что компилятор считает Method встроенным, хотя это не так,
он определен без inline спецификатора и отдельно от объявления в классе,
к тому же в опциях проекта code optimization = none,
disable inline expansions = true.
Редко увидишь такие последствия оптимизации.

Может и стоит бросить BCB...

Это было лирическое отступление.
С CREATESTRUCT я тоже уже пробовал.
Спасибо, arist, за подсказку насчет указателя на this, я передавал this прямо,
поэтому не мог понять, почему по WM_CREATE и по WM_NCCREATE разные значения.
Однако, пока никак без косяков не получается передать.
Еще такая неприятность наблюдается, сообщения приходят в следующем порядке:
WM_GETMINMAXINFO, WM_NCCREATE, WM_NCCALCSIZE, WM_CREATE
Хотелось бы выяснить, WM_GETMINMAXINFO всегда приходит первым?
Как-то нелогично это, и было бы совсем не к месту.

Тесты показали, что CoolGun скорее прав чем ошибается.
VCL абсолютно точно использует properties и записывает this
в качестве hData.
А почему, arist, SetProp не подходит? С HWND вроде все в порядке,
нет только this...
arist
0 / 0 / 0
Регистрация: 14.02.2011
Сообщений: 100
28.06.2012, 06:42     WinAPI vs VCL - Привязка к окну каких-либо данных #12
SetProp не подходит, так как нужно привязать this к окну, HWND которого ещё не известен, т.е. до или во время вызова CreateWindow.
Или я чего-то не допонимаю... ;(
John Paramol
Сообщений: n/a
28.06.2012, 08:31     WinAPI vs VCL - Привязка к окну каких-либо данных #13
HWND известен на протяжении вызова CreateWindow, по приходящим в это
время событиям (передается в WndProc вместе с Message, lParam и wParam).
Вызывать SetProp следовало бы во время обработки WM_NCCREATE,
где this передавался бы как *(lParam),
но WM_GETMINMAXINFO, мать его так, приходит первым.
SetProp подходит также как вектор. Вобщем-то с SetProp
не лучше чем с вектором, хотя, может, быстродейственнее.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.06.2012, 09:04     WinAPI vs VCL - Привязка к окну каких-либо данных
Еще ссылки по теме:

C++ Если сумма индексов каких-либо двух элементов матрицы, расположенных ниже главной диагонали, равна минимальному элементу матрицы, то..
НЕ запускается без выдачи каких либо ошибок vs 2012 C++
Cравнение каких-либо не крайних чисел, полученных в результате вычисления функции C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
arist
0 / 0 / 0
Регистрация: 14.02.2011
Сообщений: 100
28.06.2012, 09:04     WinAPI vs VCL - Привязка к окну каких-либо данных #14
Ну, я что-то типа этого и хотел сказать.

На счёт WM_GETMINMAXINFO: может пока this в WindowProc не известен, просто не
обрабатывать такие сообщения... хотя, конечно, выход такой не совсем корректен.
Yandex
Объявления
28.06.2012, 09:04     WinAPI vs VCL - Привязка к окну каких-либо данных
Ответ Создать тему
Опции темы

Текущее время: 03:28. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru