Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   Delphi | создание окна и его элементов средствами WinAPI (http://forum.oszone.net/showthread.php?t=43934)

Savant 17-01-2005 08:14 289225

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 289243

А Вы не забыли SS_LEFT какой-нибудь? Вместо WM_SETTEXT? А то WM_SETTEXT - это "сообщение", а не "стиль"

Savant 17-01-2005 09:10 289245

hasherfrog
Thanks, это у меня заскок малец :)
А проблема была в другом (Винда и с WM_SETTEXT все правильно создает): вместо Label1:=CreateWindow('Label','See me?',....) надо было Label1:=CreateWindow('STATIC','See me?',....) Это второй заскок :)

Savant 17-01-2005 09:45 289256

Кстати, вот еще интересная ситуация. Во многих примерах я видел следующее:
Код:

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 289262

Честно, я пока чего-то не догоняю, в чём проблема (не проснулся ещё :)), но можете почитать тут описание по-русски
http://www.mini-soft.net.ru/msdn/glob_1.php потом Crtl+F GetMessage

Savant 17-01-2005 10:07 289270

hasherfrog
Да не, проблемы-то нет :). Я просто указываю на то, что почти везде GetMessage() дается примерно в таком контексте
Код:

while GetMessage( lpMsg, hWnd, 0, 0 ) {...}
А у меня почему-то подобная конструкция из цикла не выходит, когда окно с хендлом hWnd закрывается :(
Цитата:

Цитата http://www.mini-soft.net.ru/msdn/glob_1.php
hWnd - дескриптор окна, сообщения для которого следует получить. Этот аргумент может принимать нулевое значение. Это значение свидетельствует о том, что функция GetMessage должна получать сообщения для любого окна, принадлежащего данному потоку, и сообщения от потока, посланные функцией PostThreadMessage

Вот когда на нуль подправил, тогда все запахало (о чем и написал постом выше)... Тогда как же использовать аргумент hWnd? :confused:

ps: 1. Я и английский знаю :)
2. Не спал еще :) , отсюда и ляпы разные

hasherfrog 17-01-2005 13:59 289368

Дык а откуда взялся hWnd? Его кто инициализировал? И как? Дайте кусок текста.

mrcnn 17-01-2005 16:20 289416

Petzold дает эту конструкцию во всех примерах в таком виде:
Код:

while (GetMessage (&msg, NULL, 0, 0))
          {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
          }


Savant 17-01-2005 18:00 289458

Уважаемый 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.

frizzn 18-01-2005 03:46 289558

Savant
Цитата:

"с нулём" (т.е. когда функция принимает все сообщения из потока) все отлично работает, гораздо более интересно, почему не работает с конкретным значением hWnd (т.е. когда функция принимает сообщения от данного окна)
AFAIK, когда приходит WM_QUIT, окно уже не существует (hWnd показывает пальцем в небо). Поэтому приходится указывать NULL, т.е. независимо от окна

Savant 18-01-2005 08:32 289588

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 289605

:lol:
http://ilyabirman.ru/meanwhile/2004/01/20/2/comments

Вообще-то, емнип, обычно hWnd используют в связке с if (PeekMessage(&msg, hWnd, ... потому что hWnd - своего рода фильтр :)


Savant 18-01-2005 09:59 289607

hasherfrog
Цитата:

Цитата http://ilyabirman.ru/meanwhile/2004/01/20/2/comments
<...> Не работает: при клике по крестику окно закрывается, а приложение — нет. Причем с F4 проверял, что WM_DESTROY приходит, PostQuitMessage вызывается, но WM_QUIT в очередь сообщений не запихивает; во всяком случае, GetMessage не возвращает 0, а должен при наличии WM_QUIT в очереди.

Прям точно что и у меня.

Цитата:

Цитата hasherfrog
... потому что 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 289610

Нет, лол вызвало "Прям точно что и у меня." :)

pva 18-01-2005 14:15 289690

Очень интересная тема, жаль что не поймал её сразу. Работает это так:
PostQuitMessage посылает сообщение PostMessage(0, 0, 0, exit_code), это значит, что до окна hwnd!=0 оно не дойдёт. После уничтожения окна, GetMessage(..., hwnd, ...) просто не вернётся, т.к. для окна hwnd сообщения никто не пошлёт. Советую не использовать такую конструкцию в главном цикле.


Время: 21:32.

Время: 21:32.
© OSzone.net 2001-