Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: WinAPI - обработка сообщений от контрола  (Прочитано 33361 раз)
0 Пользователей и 1 Гость смотрят эту тему.
FallenSoul
Опытный

ru
Offline Offline
Пол: Мужской

« : 04-04-2008 16:50 » 

Подскажите где можно нормальную информацию про сообщения найти,- именно про их реализацию в программе(теоретическую часть про цикл обработки сообщений, синх/асинх сообщения вроде разобрался),- про то как получать от объектов сообщения. Конкретно

switch(Msg)
 {
  case WM_PAINT:
    ...
  case WM_CLOSE:
    ...
  case WM_DESTROY:
    ...
// Всё что выше ясно
  case *здесь не понятно как организовать обработку сообщений от моего объекта, созданного через CreateWindow

п.с. msdn не в помощь, т.к. не представляю что там смотреть
« Последнее редактирование: 04-04-2008 20:44 от Вад » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 04-04-2008 17:04 » 

FallenSoul, структура же есть такая

The MSG structure contains message information from a thread's message queue.

Syntax

typedef struct {
    HWND hwnd;
    UINT message;
    WPARAM wParam;
    LPARAM lParam;
    DWORD time;
    POINT pt;
} MSG, *PMSG;
Members

hwnd
Handle to the window whose window procedure receives the message.
message
Specifies the message identifier. Applications can only use the low word; the high word is reserved by the system.
wParam
Specifies additional information about the message. The exact meaning depends on the value of the message member.
lParam
Specifies additional information about the message. The exact meaning depends on the value of the message member.
time
Specifies the time at which the message was posted.
pt
Specifies the cursor position, in screen coordinates, when the message was posted.


в неё поле HWND hwnd - сравнивай с хендлом твоего контрола.
Записан

FallenSoul
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 04-04-2008 17:26 » 

Алексей1153++, ты меня немножко не понял или я чтото не понимаю. Хотелось бы увидеть без кода каких либо обработок построение switch(Msg) оконной процедуры.

Код:
	switch(uMsg)
{

case WM_PAINT:

          break;

case WM_CLOSE:

break;

case WM_DESTROY:
PostQuitMessage(0);
break;

case // какой ставить case именно для того чтоб в дальнейшем обработать к примеру сообщение от дерева TVM_SELECTITEM и как построить эту обработку?


default:
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 04-04-2008 17:42 » 

ну, я бы сделал так :

Код:
if(msg->hwnd==hMyTree)
{
   switch(msg->message)
   {
      case TVM_SELECTITEM:
      {
         //...обрабатываем
      }
      break;

      case TVM_...:
      {
         //...обрабатываем
      }
      break;
  }
}

конечно, я бы в таком виде не оставил, обязательно бы для удобства подключил бы макросы, таблицы хендлов или MFC Улыбаюсь
Записан

FallenSoul
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 06-04-2008 12:50 » 

ну, я бы сделал так :

Код:
if(msg->hwnd==hMyTree)
{
   switch(msg->message)
   {
      case TVM_SELECTITEM:
      {
         //...обрабатываем
      }
      break;

      case TVM_...:
      {
         //...обрабатываем
      }
      break;
  }
}

конечно, я бы в таком виде не оставил, обязательно бы для удобства подключил бы макросы, таблицы хендлов или MFC Улыбаюсь

Попробовал обработать сообщения для дерева- не получилось ... Вот хоть убей- не могу понять как решить следующий вопрос.

Сначало ловить сообщение в оконной процедуре а потом проверять для какого окна(по хендлу) оно было посланно сравнивая hWnd(HWND hWnd-первый парамерт в CALLBACK WndProc-оконной функции) или как ты написал сначало сравнивать хендлы пришедшего сообщения а потом уже расшифровывать сообщение которое пришло сравнивая его отдельные поля?

Первое не работает.
Код:
case WM_SIZE:
    if(hWnd==hTreeView) MessageBox(NULL,"a","b",MB_OKCANCEL);
    break;
Второе не работает потому что передаётся в WndProc переменная UINT uMsg- которая сама по себе уже является идентификатором сообщения т.к. используется в свитче вида(если я не ошибаюсь)

Код:
switch(uMsg)
{
case WM_CREATE:
break;

case WM_PAINT:
             break;

default:
return DefWindowProc(hWnd,uMsg,wParam,lParam);
          }

need help  А черт его знает...
« Последнее редактирование: 06-04-2008 12:52 от FallenSoul » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 06-04-2008 12:59 » 

FallenSoul, скинь проект , так долго гадать будем. Всё берётся и пробуется в отладчике Улыбаюсь

только удали папки релиза и дебага - или что там будет
Записан

FallenSoul
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 06-04-2008 13:03 » 

Вот

* Second.rar (17.39 Кб - загружено 1109 раз.)
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 06-04-2008 13:52 » 

скомпилилось, правда структуру WINDOWINFO пришлось из мсдн так вставить, не находит почему то

typedef struct {
    DWORD cbSize;
    RECT rcWindow;
    RECT rcClient;
    DWORD dwStyle;
    DWORD dwExStyle;
    DWORD dwWindowStatus;
    UINT cxWindowBorders;
    UINT cyWindowBorders;
    ATOM atomWindowType;
    WORD wCreatorVersion;
} WINDOWINFO, *PWINDOWINFO, *LPWINDOWINFO;


У тебя какой то бардак с хендлами, начиная с того, что хендл главного окна ты вообще не запоминаешь ) Щас попробую разобраться
Записан

FallenSoul
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 06-04-2008 14:42 » 

скомпилилось, правда структуру WINDOWINFO пришлось из мсдн так вставить, не находит почему то

typedef struct {
    DWORD cbSize;
    RECT rcWindow;
    RECT rcClient;
    DWORD dwStyle;
    DWORD dwExStyle;
    DWORD dwWindowStatus;
    UINT cxWindowBorders;
    UINT cyWindowBorders;
    ATOM atomWindowType;
    WORD wCreatorVersion;
} WINDOWINFO, *PWINDOWINFO, *LPWINDOWINFO;


У тебя какой то бардак с хендлами, начиная с того, что хендл главного окна ты вообще не запоминаешь ) Щас попробую разобраться

Чтоб WINDOFINFO у меня работал, менял где то в .h файле #define с 0х410 на 0х510, только не помню какой именно

2А разобраться и в самом деле очень хотелось бы Улыбаюсь А то на майских праздниках как-то не найс за курсачём просиживать
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 06-04-2008 15:03 » 

FallenSoul, в общем, главной проблемы я не решил - не могу понять, как назначить дереву оконную процедуру (она - другая должна быть, потому что в оконную процедуру главного окна сообщения контрола не летят)

Ну а в остальном я сделал такие изменения:
ввёл структуру
Код:
struct s_MyHandles
{
HWND hTreeView;
HWND hMainWnd;
s_MyHandles()
{
hTreeView=0;
hMainWnd=0;
}

}m_myhandles;

- туда сохраняем все нужные глобальные хендлы

а главная оконная процедура (основной её код) у меня вышла такой
Код:
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:
{
m_myhandles.hTreeView=CreateWindow(
WC_TREEVIEW,NULL,WS_SIZEBOX|WS_VISIBLE|WS_CHILD|TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT,
CW_USEDEFAULT,CW_USEDEFAULT,300,668,
hWnd,(HMENU)NULL,
(HINSTANCE)hInstance,NULL
);

//Fill_TopKeys(hTreeView,hWnd);
}
break;

case WM_DESTROY:
{
//без этого процесс остаётся висеть в озу!
exit(0);
}
break;
}

return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

насчёт
      case WM_DESTROY:
      {
         //без этого процесс остаётся висеть в озу!
         exit(0);
      }
      break;

- я не нашёл, как побороть иначе...

Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 06-04-2008 15:19 » 

вот я что нашёл
http://www.cyberguru.ru/programming/win32/win32-windows-page29.html

и, похоже, идентификаторы контролов задаются вместо хендла меню в CreateWindow -

(HMENU) (int) (ID_...),
Записан

FallenSoul
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 06-04-2008 17:58 » 

Алексей1153++, так вопрос остаётся в силе =) Как всё таки обработать сообщение которое посылается дереву на изменение размеров?

2За структурку спасибо- буду юзать
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 06-04-2008 18:26 » 

пока не знаю, щас поищу
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #13 : 06-04-2008 19:13 » 

подогнать размер получилось так
Код:
		case WM_SIZE:
{
RECT rMainClient;
GetClientRect(m_myhandles.hMainWnd,&rMainClient);
RECT rTree;
GetWindowRect(m_myhandles.hTreeView,&rTree);

MoveWindow(m_myhandles.hTreeView,
0,0,
rTree.right-rTree.left,
rMainClient.bottom-rMainClient.top,
1
);
}
break;

но это когда меняют размер главного окно. Как назначить процедуру для контрола я так и не понял ((

Ром, подскажи, знаешь может ?
Записан

FallenSoul
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 07-04-2008 15:38 » 

Незнаю, в тему ли я скажу-но всё же. Сегодня пока было время, на Речном Вокзале в книжном почитал книг по Visual C++,- конкретно про обработку сообщений. Вычитал что у каждой формы(контрола) как минимум свой идентификатор и у дерева это TVS_,- знач толку ловить сообщение WM_SIZE в оконной процедуре родительского окна вообще никакого. Этим я наверно подтвердил твои слова, Алексей1153++ =) И так же поддерживаю вопрос как написать эту оконную процедуру для дерева, а точнее как её связать с программой. (Для дочернего окна если нужна оконная процедура, то в одном из полей перед регистрацией окна указывается её имя(пишется собственная, отличная от WndProc функция). Но это наверно опять не в тему, т.к. окно мы регистрируем а дерево является базовым классом не требующим регистрации).
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #15 : 07-04-2008 15:53 » 

FallenSoul, я , наверное, не смогу больше подсказать, а разбираться мне щас некогда ((( Лучше на MFC пиши - там удобнее
Записан

FallenSoul
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 07-04-2008 18:20 » 

А я хотел ещё туда окно с полями добавить справа от дерева,и при изменении размеров одного из элементов,чтобы автоматически бы изменялся размер второго,- по полной аналогии regedit'a. Видать не суждено видеть моему преподователю такой исходник Улыбаюсь
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #17 : 07-04-2008 18:43 » 

FallenSoul, ну ежели разберёшься - суждено Ага И мне тоже покажешь, как
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #18 : 07-04-2008 18:45 » 

MSDN даёт такой пример изменения процедуры для эдита:
Код: (C++)
WNDPROC wpOrigEditProc;
 
LRESULT APIENTRY EditBoxProc(
    HWND hwndDlg,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam)
{
    HWND hwndEdit;
 
    switch(uMsg)
    {
        case WM_INITDIALOG:
            // Retrieve the handle to the edit control.
            hwndEdit = GetDlgItem(hwndDlg, ID_EDIT);
 
            // Subclass the edit control.
            wpOrigEditProc = (WNDPROC) SetWindowLong(hwndEdit,
                GWL_WNDPROC, (LONG) EditSubclassProc);
            //
            // Continue the initialization procedure.
            //
            return TRUE;
 
        case WM_DESTROY:
            // Remove the subclass from the edit control.
            SetWindowLong(hwndEdit, GWL_WNDPROC,
                (LONG) wpOrigEditProc);
            //
            // Continue the cleanup procedure.
            //
            break;
    }
    return FALSE;
        UNREFERENCED_PARAMETER(lParam);
}
 
// Subclass procedure
LRESULT APIENTRY EditSubclassProc(
    HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam)
{
    if (uMsg == WM_GETDLGCODE)
        return DLGC_WANTALLKEYS;
 
    return CallWindowProc(wpOrigEditProc, hwnd, uMsg,
        wParam, lParam);
}

Всё делается через SetWindowLong. Заменил на TreeView, вставил обработку WM_SIZE в процедуру из приаттаченного выше семпла, работает Улыбаюсь
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #19 : 07-04-2008 18:58 » 

вот, как раз то, что мы и искали ) Точняк!

SetWindowLong

Цитата
The SetWindowLong function changes an attribute of the specified window. The function also sets the 32-bit (long) value at the specified offset into the extra window memory.

Note  This function has been superseded by the SetWindowLongPtr function. To write code that is compatible with both 32-bit and 64-bit versions of Microsoft® Windows®, use the SetWindowLongPtr function.

Syntax

LONG SetWindowLong(          HWND hWnd,
    int nIndex,
    LONG dwNewLong
);
Parameters

hWnd
[in]
Handle to the window and, indirectly, the class to which the window belongs.

Windows 95/98/Me: The SetWindowLong function may fail if the window specified by the hWnd parameter does not belong to the same process as the calling thread.

nIndex
[in] Specifies the zero-based offset to the value to be set. Valid values are in the range zero through the number of bytes of extra window memory, minus the size of an integer. To set any other value, specify one of the following values.
GWL_EXSTYLE
Sets a new extended window style. For more information, see CreateWindowEx.
GWL_STYLE
Sets a new window style.
GWL_WNDPROC
Sets a new address for the window procedure.

Windows NT/2000/XP: You cannot change this attribute if the window does not belong to the same process as the calling thread.

GWL_HINSTANCE
Sets a new application instance handle.
GWL_ID
Sets a new identifier of the window.
GWL_USERDATA
Sets the user data associated with the window. This data is intended for use by the application that created the window. Its value is initially zero.
The following values are also available when the hWnd parameter identifies a dialog box.
DWL_DLGPROC
Sets the new address of the dialog box procedure.
DWL_MSGRESULT
Sets the return value of a message processed in the dialog box procedure.
DWL_USER
Sets new extra information that is private to the application, such as handles or pointers.
dwNewLong
[in] Specifies the replacement value.
Return Value

If the function succeeds, the return value is the previous value of the specified 32-bit integer.

If the function fails, the return value is zero. To get extended error information, call GetLastError.

If the previous value of the specified 32-bit integer is zero, and the function succeeds, the return value is zero, but the function does not clear the last error information. This makes it difficult to determine success or failure. To deal with this, you should clear the last error information by calling SetLastError(0) before calling SetWindowLong. Then, function failure will be indicated by a return value of zero and a GetLastError result that is nonzero.

ай, да Вад ))
Записан

FallenSoul
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 07-04-2008 19:12 » 

Я конечно извиняюсь, но как бы это могло помочь мне в обработке сообщения от моего дерева? То что это ставится в case обработки дерева я понял, но как сам case организовать? В дополнительной оконной процедуре или я опять чтото не понимаю =\
« Последнее редактирование: 07-04-2008 19:15 от FallenSoul » Записан
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #21 : 07-04-2008 19:21 » 

FallenSoul, ну если ты хочешь обрабатывать именно оконные сообщения от дерева, а не нотификации родительскому окну, то это нужно делать в дополнительной оконной процедуре, которую ты переназначаешь описанным способом через SetWindowLong
Записан
FallenSoul
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 07-04-2008 19:22 » 

Вад, а если нотификации?
Записан
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #23 : 07-04-2008 19:34 » 

А если нотификации, то WM_NOTIFY обрабатывать в процедуре родительского окна. См. MSDN на сабж, вот оттуда пример:
Код: (C++)
switch (message)
    {
    case WM_NOTIFY:
        switch (((LPNMHDR)lParam)->code)
        {
        case CUSTOM_SELCHANGE:
            if (((LPNMHDR)lParam)->idFrom == IDC_CUSTOMLISTBOX1)
            {
                ...   // Respond to message.
                return TRUE;
            }
            break;
        ... // More cases on WM_NOTIFY switch.
        break;
        }
    ...  // More cases on message switch.
    }

http://msdn2.microsoft.com/en-us/library/bb775583(VS.85).aspx
Записан
FallenSoul
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #24 : 07-04-2008 20:36 » 

Код:
		case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code)
{
case NM_CLICK:
if(((LPNMHDR)lParam)->idFrom == IDC_TREEVIEW)
{
MessageBox(NULL,"1","1",MB_OKCANCEL);
return TRUE;
}
break;
}

При клике в область дерева выдаётся окошко,- просто нет слов как благодарен вам за терпение Улыбаюсь Только вот вопрос всё таки,- сообщений нотификаций всего
Код:
NM_CHAR  
NM_CLICK 
NM_CUSTOMDRAW 
NM_DBLCLK 
NM_HOVER 
NM_KEYDOWN 
NM_KILLFOCUS 
NM_NCHITTEST 
NM_OUTOFMEMORY 
NM_RCLICK 
NM_RDBLCLK 
NM_RELEASEDCAPTURE 
NM_RETURN 
NM_SETCURSOR 
NM_SETFOCUS 

вот столько?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #25 : 08-04-2008 03:17 » 

нотификации не спасут мир, их столько, сколько захотел контрол. А переопределённая оконная процедура позволит все сообщения обработать
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #26 : 08-04-2008 03:54 » 

FallenSoul, смотри в MSDN список нотификаций для дерева, оно ещё кой-что умеет Улыбаюсь Для каждого контрола ещё специфичные нотификации есть.
Записан
FallenSoul
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #27 : 08-04-2008 19:55 » 

Вот столкнулся с небольшой проблемой.
Создал TreeList и написал функцию заполнения колонками. Далее хочу попробовать чем то заполнить все эти поля, однако не получается.
Код:
void Fill_ListView(HWND hListView)
{
LV_COLUMN ColumnInsert;
LVITEM LvInsertStruct;

int ColumnWidth[3]={200,100,300};
char* ColumnNames[3]={"Имя","Тип","Значение"};
ColumnInsert.mask=LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
ColumnInsert.fmt=LVCFMT_LEFT;


for(int i=0;i<3;i++)
{
ColumnInsert.iSubItem=i;
ColumnInsert.cx=ColumnWidth[i];
ColumnInsert.pszText=ColumnNames[i];
ListView_InsertColumn(hListView,i,&ColumnInsert);
}


LvInsertStruct.mask=LVIF_TEXT|LVIF_PARAM;
LvInsertStruct.pszText = "sdsdsd";
for(i=0;i<3;i++)
{
for(int j=0;j<4;j++)
{
LvInsertStruct.iItem = j;
LvInsertStruct.iSubItem = i;
    ListView_InsertItem(hListView, &LvInsertStruct);
}
}
}
По логике вещей все 3 столбца должны быть заполнены одинаковыми записями в кол-ве 4х штук, однако заполнен только первый.
В поиске нашёл, чтоб проблема столбцов решается через ListView_SetItem, но не разобрался каким образом.
« Последнее редактирование: 09-04-2008 04:28 от FallenSoul » Записан
FallenSoul
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #28 : 09-04-2008 13:30 » new

Разобрался. Функция ListView_SetItemText.

Код:
void WINAPI ListView_SetItemText( 
  HWND hwnd,
  int i,
  int iSubItem,
  LPCSTR pszText
);
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines