Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Приложение после закрытия остается висеть в процессах / 11 сообщений из 11, страница 1 из 1
25.11.2018, 13:55
    #39738167
amadeus
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Приложение после закрытия остается висеть в процессах
Есть программа, создающая новое полноэкранное окно и выполняющая некоторые действия. Основной код программы:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
program prog;

uses
  windows,
  messages,
  window in 'window.pas';

{$APPTYPE GUI}

var
  window: TWindow;
  stop: Boolean = false;

begin
  window := TWindow.create("myProg");

  while (not stop) do begin
    sleep(10);
    stop := not window.update();
  end;

  window.free();
end.



Код модуля "window.pas":
Код: pascal
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.
101.
102.
103.
104.
105.
unit window;

interface

uses
  windows, messages, sysUtils;

type
  TWindowError = class(Exception);

  TWindow = class(TObject)
  private
    FName: String;
    FHandle: HWnd;
  public
    constructor create(name: String); virtual;
    destructor destroy(); override;
    function update(): boolean;
  end;

implementation

function wndProc(window: HWnd; msgId, wParam, lParam: LongInt): LongInt; stdcall; export;
var
  msg: TMessage;
begin
  msg.msg := msgId;

  case msgId of
    WM_DESTROY: postQuitMessage(0);
  else
    wndProc := DefWindowProc(window, msgId, wParam, lParam);
    exit();
  end;

  result := msg.Result
end;

constructor TWindow.create(name: String);
var
  wndClass: TWndClass;
begin
  FName := name;

  wndClass.style := CS_HREDRAW or CS_VREDRAW;
  wndClass.cbClsExtra := 0;
  wndClass.cbWndExtra := 0;
  wndClass.hInstance := hInstance;
  wndClass.hIcon := loadIcon(0, IDI_INFORMATION);
  wndClass.hCursor := loadCursor(0, IDC_ARROW);
  wndClass.hbrBackground := hBrush(getStockObject(BLACK_BRUSH));
  wndClass.lPszMenuName := nil;
  wndClass.lPszClassName := PWideChar(name);
  wndClass.lpfnWndProc := @wndProc;

  if (registerClass(wndClass) <> 0) then begin
    FHandle := createWindow(
      PWideChar(name),
      PWideChar(name),
      WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      0,
      0,
      hInstance,
      nil
    );

    if (FHandle <> 0) then begin
      setWindowLong(FHandle, GWL_STYLE, WS_POPUP);
      showWindow(FHandle, SW_MAXIMIZE);
    end
    else TWindowError.create('Не удается создать окно.');
  end
  else
    raise TWindowError.create('Не удается зарегистрировать класс.');
end;

destructor TWindow.destroy();
begin
  destroyWindow(FHandle);

  inherited;
end;

function TWindow.update(): boolean;
var
  msg: TMsg;
begin
  result := true;

  while (peekMessage(msg, FHandle, 0, 0, 0)) do begin
    if (getMessage(msg, FHandle, 0, 0)) then begin
      translateMessage(msg);
      dispatchMessage(msg);

      if (msg.message = WM_DESTROY) then
      exit(false);
    end;
  end;
end;

end.



Проблема в том, что программа при закрытии окна остается висеть в диспетчере задач - видимо, цикл работает, не проходит до этой строки:

Код: pascal
1.
window.free();



А это значит, что метод "TWindow.update" не возвращает false, хотя должен при получении "WM_DESTROY"... В чем я ошибся?
...
Рейтинг: 0 / 0
25.11.2018, 14:38
    #39738177
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Приложение после закрытия остается висеть в процессах
amadeusВ чем я ошибся?

Во-первых, в возвращаемых значениях оконной функции.
amadeusметод "TWindow.update" не возвращает false
Не вижу строчки в которой там упоминается false.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
25.11.2018, 15:36
    #39738190
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Приложение после закрытия остается висеть в процессах
Dimitry SibiryakovНе вижу
Код: pascal
1.
exit(false);
...
Рейтинг: 0 / 0
25.11.2018, 16:22
    #39738204
Гирлионайльдо
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Приложение после закрытия остается висеть в процессах
А как это, работает у вас ?

Код: pascal
1.
  window := TWindow.create("myProg");
...
Рейтинг: 0 / 0
25.11.2018, 21:05
    #39738266
amadeus
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Приложение после закрытия остается висеть в процессах
авторВо-первых, в возвращаемых значениях оконной функции.

В чем именно там ошибка?
...
Рейтинг: 0 / 0
25.11.2018, 21:51
    #39738271
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Приложение после закрытия остается висеть в процессах
amadeusВ чем именно там ошибка?

Безмозглый копипаст вижу я. А вот инициализацию msg.Result - нет. А ведь
MSDNReturn Value

If an application processes this message, it should return zero.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
26.11.2018, 08:12
    #39738352
amadeus
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Приложение после закрытия остается висеть в процессах
Код: pascal
1.
2.
3.
4.
5.
6.
7.
  msg.msg := msgId;

  case msgId of
    WM_DESTROY: postQuitMessage(0);
  else
    result := defWindowProc(window, msgId, wParam, lParam);
  end;



Оставил такой код в этой функции, но ошибка все равно есть. Возможно, проблема не здесь, а в чем-то еще.
...
Рейтинг: 0 / 0
26.11.2018, 09:34
    #39738365
amadeus
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Приложение после закрытия остается висеть в процессах
Думаю, проблема в том, что коды сообщений, получаемых после вызова "getMessage" и в "wndProc", разные. Поэтому может не работать проверка на "WM_DESTROY" в "update".
...
Рейтинг: 0 / 0
26.11.2018, 11:33
    #39738427
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Приложение после закрытия остается висеть в процессах
amadeus,

Проблема в том, что надо уметь читать документацию:

Microsoft DocsThe PostQuitMessage function posts a WM_QUIT message to the thread's message queue and returns immediately; the function simply indicates to the system that the thread is requesting to quit at some time in the future.GetMessage ParametershWnd

Type: HWND

A handle to the window whose messages are to be retrieved. The window must belong to the current thread.

If hWnd is NULL, GetMessage retrieves messages for any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL (see the MSG structure). Therefore if hWnd is NULL, both window messages and thread messages are processed. PeekMessageW ParametershWnd

Type: HWND

A handle to the window whose messages are to be retrieved. The window must belong to the current thread.

If hWnd is NULL, PeekMessage retrieves messages for any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL (see the MSG structure). Therefore if hWnd is NULL, both window messages and thread messages are processed.

Я выделил жирным критичные моменты, в принципе этого должно хватить чтобы понять почему не работает. Если вдруг не хватит, то под катом - код, который у меня работает.
Ахтунг! Delphi 7
Код: pascal
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.
program apiform;

uses
  Windows,
  Messages,
  SysUtils;

type
  TWindowError = class(Exception);

  TWindow = class(TObject)
  private
    FName: String;
    FHandle: HWnd;
  public
    constructor create(name: string); virtual;
    function update(): boolean;
  end;

function wndProc(window: HWnd; msgId, wParam, lParam: LongInt): LongInt; stdcall;
begin
  if msgId = WM_DESTROY then
    postQuitMessage(0);
  Result := DefWindowProc(window, msgId, wParam, lParam); // call DestroyWindow() on WM_DESTROY
end;

constructor TWindow.create(Name: string);
var
  wndClass: TWndClass;
begin
  FName := Name;

  wndClass.style := CS_HREDRAW or CS_VREDRAW;
  wndClass.cbClsExtra := 0;
  wndClass.cbWndExtra := 0;
  wndClass.hInstance := hInstance;
  wndClass.hIcon := loadIcon(0, IDI_INFORMATION);
  wndClass.hCursor := loadCursor(0, IDC_ARROW);
  wndClass.hbrBackground := hBrush(getStockObject(BLACK_BRUSH));
  wndClass.lPszMenuName := nil;
  wndClass.lPszClassName := PChar(Name);
  wndClass.lpfnWndProc := @wndProc;

  if (registerClass(wndClass) <> 0) then begin
    FHandle := createWindow(
      PChar(name),
      PChar(name),
      WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      0,
      0,
      hInstance,
      nil
    );

    if (FHandle <> 0) then begin
      setWindowLong(FHandle, GWL_STYLE, WS_POPUP);
      showWindow(FHandle, SW_MAXIMIZE);
    end
    else TWindowError.create('CreateWindow error.');
  end
  else
    raise TWindowError.create('RegisterClass error.');
end;

function TWindow.update(): boolean;
var
  msg: TMsg;
begin
  Result := False;
  while (PeekMessage(msg, 0, 0, 0, 0)) do
  begin
    if GetMessage(msg, 0, 0, 0) then
    begin
      TranslateMessage(msg);
      DispatchMessage(msg);
    end else
      Exit;
  end;
  Result := True;
end;

begin
  with TWindow.create('myProg') do
  try
    while update() do
      sleep(10);
  finally
    Free;
  end;
end.


...
Рейтинг: 0 / 0
26.11.2018, 12:52
    #39738503
amadeus
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Приложение после закрытия остается висеть в процессах
alekcvp , спасибо, буду разбираться.
...
Рейтинг: 0 / 0
26.11.2018, 14:15
    #39738575
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Приложение после закрытия остается висеть в процессах
amadeusОставил такой код в этой функции

Прелестно... Т.е. ты вообще забил на процитированное мною "функция должна возвращать..."
или просто не смог это прочитать?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Приложение после закрытия остается висеть в процессах / 11 сообщений из 11, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]