FallenSoul
|
|
« : 04-04-2008 16:50 » |
|
Подскажите где можно нормальную информацию про сообщения найти,- именно про их реализацию в программе(теоретическую часть про цикл обработки сообщений, синх/асинх сообщения вроде разобрался),- про то как получать от объектов сообщения. Конкретно
switch(Msg) { case WM_PAINT: ... case WM_CLOSE: ... case WM_DESTROY: ... // Всё что выше ясно case *здесь не понятно как организовать обработку сообщений от моего объекта, созданного через CreateWindow
п.с. msdn не в помощь, т.к. не представляю что там смотреть
|
|
« Последнее редактирование: 04-04-2008 20:44 от Вад »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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
|
|
« Ответ #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); }
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #3 : 04-04-2008 17:42 » |
|
ну, я бы сделал так : if(msg->hwnd==hMyTree) { switch(msg->message) { case TVM_SELECTITEM: { //...обрабатываем } break;
case TVM_...: { //...обрабатываем } break; } }
конечно, я бы в таком виде не оставил, обязательно бы для удобства подключил бы макросы, таблицы хендлов или MFC
|
|
|
Записан
|
|
|
|
FallenSoul
|
|
« Ответ #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 »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #5 : 06-04-2008 12:59 » |
|
FallenSoul, скинь проект , так долго гадать будем. Всё берётся и пробуется в отладчике только удали папки релиза и дебага - или что там будет
|
|
|
Записан
|
|
|
|
FallenSoul
|
|
« Ответ #6 : 06-04-2008 13:03 » |
|
Вот
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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
|
|
« Ответ #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А разобраться и в самом деле очень хотелось бы А то на майских праздниках как-то не найс за курсачём просиживать
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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; - я не нашёл, как побороть иначе...
|
|
|
Записан
|
|
|
|
|
FallenSoul
|
|
« Ответ #11 : 06-04-2008 17:58 » |
|
Алексей1153++, так вопрос остаётся в силе =) Как всё таки обработать сообщение которое посылается дереву на изменение размеров?
2За структурку спасибо- буду юзать
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #12 : 06-04-2008 18:26 » |
|
пока не знаю, щас поищу
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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
|
|
« Ответ #14 : 07-04-2008 15:38 » |
|
Незнаю, в тему ли я скажу-но всё же. Сегодня пока было время, на Речном Вокзале в книжном почитал книг по Visual C++,- конкретно про обработку сообщений. Вычитал что у каждой формы(контрола) как минимум свой идентификатор и у дерева это TVS_,- знач толку ловить сообщение WM_SIZE в оконной процедуре родительского окна вообще никакого. Этим я наверно подтвердил твои слова, Алексей1153++ =) И так же поддерживаю вопрос как написать эту оконную процедуру для дерева, а точнее как её связать с программой. (Для дочернего окна если нужна оконная процедура, то в одном из полей перед регистрацией окна указывается её имя(пишется собственная, отличная от WndProc функция). Но это наверно опять не в тему, т.к. окно мы регистрируем а дерево является базовым классом не требующим регистрации).
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #15 : 07-04-2008 15:53 » |
|
FallenSoul, я , наверное, не смогу больше подсказать, а разбираться мне щас некогда ((( Лучше на MFC пиши - там удобнее
|
|
|
Записан
|
|
|
|
FallenSoul
|
|
« Ответ #16 : 07-04-2008 18:20 » |
|
А я хотел ещё туда окно с полями добавить справа от дерева,и при изменении размеров одного из элементов,чтобы автоматически бы изменялся размер второго,- по полной аналогии regedit'a. Видать не суждено видеть моему преподователю такой исходник
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #17 : 07-04-2008 18:43 » |
|
FallenSoul, ну ежели разберёшься - суждено И мне тоже покажешь, как
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #18 : 07-04-2008 18:45 » |
|
MSDN даёт такой пример изменения процедуры для эдита: 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 в процедуру из приаттаченного выше семпла, работает
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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
|
|
« Ответ #20 : 07-04-2008 19:12 » |
|
Я конечно извиняюсь, но как бы это могло помочь мне в обработке сообщения от моего дерева? То что это ставится в case обработки дерева я понял, но как сам case организовать? В дополнительной оконной процедуре или я опять чтото не понимаю =\
|
|
« Последнее редактирование: 07-04-2008 19:15 от FallenSoul »
|
Записан
|
|
|
|
Вад
|
|
« Ответ #21 : 07-04-2008 19:21 » |
|
FallenSoul, ну если ты хочешь обрабатывать именно оконные сообщения от дерева, а не нотификации родительскому окну, то это нужно делать в дополнительной оконной процедуре, которую ты переназначаешь описанным способом через SetWindowLong
|
|
|
Записан
|
|
|
|
FallenSoul
|
|
« Ответ #22 : 07-04-2008 19:22 » |
|
Вад, а если нотификации?
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #23 : 07-04-2008 19:34 » |
|
А если нотификации, то WM_NOTIFY обрабатывать в процедуре родительского окна. См. MSDN на сабж, вот оттуда пример: 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
|
|
« Ответ #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
вот столько?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #25 : 08-04-2008 03:17 » |
|
нотификации не спасут мир, их столько, сколько захотел контрол. А переопределённая оконная процедура позволит все сообщения обработать
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #26 : 08-04-2008 03:54 » |
|
FallenSoul, смотри в MSDN список нотификаций для дерева, оно ещё кой-что умеет Для каждого контрола ещё специфичные нотификации есть.
|
|
|
Записан
|
|
|
|
FallenSoul
|
|
« Ответ #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
|
|
« Ответ #28 : 09-04-2008 13:30 » |
|
Разобрался. Функция ListView_SetItemText. void WINAPI ListView_SetItemText( HWND hwnd, int i, int iSubItem, LPCSTR pszText );
|
|
|
Записан
|
|
|
|
|