Показать полную графическую версию : Delphi | создание окна и его элементов средствами WinAPI
Подскажите, в чем трабл...
........
handleWnd:=CreateWindow(myClassName, 'See a label below?', WS_OVERLAPPEDWINDOW,400,300,200,100,0,0,hInstance,nil);
if handleWnd = 0 then begin // окно создается
MessageBox(0,'Failed to create Window',nil,MB_OK);
Exit;
end;
Label1:=CreateWindow('Label','See me?',WS_VISIBLE or WS_CHILD or WM_SETTEXT,10,10,60,23,handleWnd,0,hInstance,nil);
if Label1 = 0 then begin // а текст нет :(
MessageBox(0, 'Failed to create Label', nil, MB_OK);
Exit;
end;
........
hasherfrog
17-01-2005, 09:03
А Вы не забыли SS_LEFT какой-нибудь? Вместо WM_SETTEXT? А то WM_SETTEXT - это "сообщение", а не "стиль"
hasherfrog
Thanks, это у меня заскок малец :)
А проблема была в другом (Винда и с WM_SETTEXT все правильно создает): вместо Label1:=CreateWindow('Label','See me?',....) надо было Label1:=CreateWindow('STATIC','See me?',....) Это второй заскок :)
Кстати, вот еще интересная ситуация. Во многих примерах я видел следующее:
while GetMessage( lpMsg, hWnd, 0, 0 ) do begin
TranslateMessage( lpMsg );
DispatchMessage( lpMsg );
end;
У меня подобная конструкция приводит к тому, что окно после WM_DESTROY разрушается, а из цикла программа не выходит! Исправляю на GetMessage( lpMsg, 0, 0, 0 ) и все "ок". Кто-нибудь может это прокомментировать?
hasherfrog
17-01-2005, 09:56
Честно, я пока чего-то не догоняю, в чём проблема (не проснулся ещё :)), но можете почитать тут описание по-русски
http://www.mini-soft.net.ru/msdn/glob_1.php потом Crtl+F GetMessage
hasherfrog
Да не, проблемы-то нет :). Я просто указываю на то, что почти везде GetMessage() дается примерно в таком контекстеwhile GetMessage( lpMsg, hWnd, 0, 0 ) {...}А у меня почему-то подобная конструкция из цикла не выходит, когда окно с хендлом hWnd закрывается :(
hWnd - дескриптор окна, сообщения для которого следует получить. Этот аргумент может принимать нулевое значение. Это значение свидетельствует о том, что функция GetMessage должна получать сообщения для любого окна, принадлежащего данному потоку, и сообщения от потока, посланные функцией PostThreadMessage
Вот когда на нуль подправил, тогда все запахало (о чем и написал постом выше)... Тогда как же использовать аргумент hWnd? :confused:
ps: 1. Я и английский знаю :)
2. Не спал еще :) , отсюда и ляпы разные
hasherfrog
17-01-2005, 13:59
Дык а откуда взялся hWnd? Его кто инициализировал? И как? Дайте кусок текста.
Petzold дает эту конструкцию во всех примерах в таком виде:
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
Уважаемый mrcnn, я знаю, что "с нулём" (т.е. когда функция принимает все сообщения из потока) все отлично работает, гораздо более интересно, почему не работает с конкретным значением hWnd (т.е. когда функция принимает сообщения от данного окна).
Уважаемый hasherfrog, вот нарезка кода:
var
Msg: TMsg; // аналог MSG в Си
handleWnd, Label1 : THandle; // аналог HWND в Си
.........
handleWnd:=CreateWindow(myClassName,'See a label below?',WS_OVERLAPPEDWINDOW,0,0,200,100,hWndParent,0,hInstance,nil);
if handleWnd = 0 then
if MessageBox(0,'Failed to create Window'#13'Close Application?',nil,MB_TASKMODAL or MB_ICONWARNING or MB_OKCANCEL)=ID_OK then
Exit;
Label1:=CreateWindow('STATIC','See me?',WS_VISIBLE or WS_CHILD or WM_SETTEXT,10,10,60,23,handleWnd,0,hInstance,nil);
if Label1 = 0 then
if MessageBox(0,'Failed to create Label'#13'Close Application?',nil,MB_TASKMODAL or MB_ICONWARNING or MB_OKCANCEL)=ID_OK then
Exit;
.........
ShowWindow(handleWnd, SW_SHOW);
UpdateWindow(handleWnd);
while GetMessage(Msg, handleWnd, 0, 0) do begin // если вместо handleWnd поставить 0, то все отлично
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
.........
Проблема в том, что программа не выходит из цикла while.
Savant
"с нулём" (т.е. когда функция принимает все сообщения из потока) все отлично работает, гораздо более интересно, почему не работает с конкретным значением hWnd (т.е. когда функция принимает сообщения от данного окна)
AFAIK, когда приходит WM_QUIT, окно уже не существует (hWnd показывает пальцем в небо). Поэтому приходится указывать NULL, т.е. независимо от окна
frizzn
О'кей, тогда переделаем нижнюю часть в такую конструкцию:
...........
while GetMessage(Msg, handleWnd, 0, 0) do begin
if Msg.message=WM_DESTROY then Break;
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
MessageBox(0,'Yeah :(','Can't see me?',MB_OK);
..........
WM_DESTROY ведь посылается когда окно еще живо, так? А из цикла программа не выходит все равно. Или я опять чего-то наврал?..
hasherfrog
18-01-2005, 09:47
:lol:
http://ilyabirman.ru/meanwhile/2004/01/20/2/comments
Вообще-то, емнип, обычно hWnd используют в связке с if (PeekMessage(&msg, hWnd, ... потому что hWnd - своего рода фильтр :)
hasherfrog
<...> Не работает: при клике по крестику окно закрывается, а приложение — нет. Причем с F4 проверял, что WM_DESTROY приходит, PostQuitMessage вызывается, но WM_QUIT в очередь сообщений не запихивает; во всяком случае, GetMessage не возвращает 0, а должен при наличии WM_QUIT в очереди.
Прям точно что и у меня.
... потому что hWnd - своего рода фильтр
О'кей, фильтр... Но почему тогда в Windows SDK (в старом, в msdn еще не смотрел) дан пример:
while (GetMessage( lpMsg, hWnd, 0, 0)) ...
ps: a lol вызвало "if Msg.message=WM_DESTROY then Break;"? Не волнуйтесь, у меня колбэк (callback) есть...
hasherfrog
18-01-2005, 10:07
Нет, лол вызвало "Прям точно что и у меня." :)
Очень интересная тема, жаль что не поймал её сразу. Работает это так:
PostQuitMessage посылает сообщение PostMessage(0, 0, 0, exit_code), это значит, что до окна hwnd!=0 оно не дойдёт. После уничтожения окна, GetMessage(..., hwnd, ...) просто не вернётся, т.к. для окна hwnd сообщения никто не пошлёт. Советую не использовать такую конструкцию в главном цикле.
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.