Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 18.06.2014, 00:26   #1
Питерский2
Пользователь
 
Регистрация: 20.05.2014
Сообщений: 29
По умолчанию Не ловится QUERYENDSESSION

СтоИт задача выполнить некоторые действия (сохранение резервных копий) при выключении компьютера. Решил создать "окно только для сообщений" и отлавливать выключение в нем.

Msg - структура MONMSGSTRUCT
HWND_MESSAGE - согласно ВинАпи, такой параметр надо передать как родительское окно для создания "message-only window"

Код:
Invoke GetModuleHandle,0 
Mov [hInst], EAX

       mov   wc.style, CS_NOCLOSE
       mov   wc.lpfnWndProc, Offset WndProc
       mov   wc.cbClsExtra,NULL
       mov   wc.cbWndExtra,NULL
       Mov   wc.hInstance, EAX
       mov   wc.hbrBackground,COLOR_WINDOW+1
       mov   wc.lpszMenuName,NULL
       mov   wc.lpszClassName,OFFSET WinClName
       invoke LoadIcon,NULL,IDI_APPLICATION         
       mov   wc.hIcon,eax
       invoke LoadCursor,NULL,IDC_ARROW
       mov   wc.hCursor,eax
Invoke RegisterClass, Offset wc    ;Регистрируем класс окна

Invoke CreateWindowEx,WS_EX_RTLREADING,Offset WinClName,Offset WinName, WS_MINIMIZE,CW_USEDEFAULT,CW_USEDEFAULT,20h,20h,HWND_MESSAGE,0,[hInst],0    ;Создали окно

Invoke ShowWindow, EAX, SW_NORMAL

; Цикл выборки сообщений
Cukl:
Invoke GetMessage, Offset Msg,0,0,0
Test EAX,EAX
Jz Exit_Cukl
Push Offset Msg
Call DispatchMessage
Jmp Cukl
Exit_Cukl:

;Оконная процедура
WndProc1 Proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.if (uMsg==WM_QUERYENDSESSION)
;.........    КОД НЕ ВЫПОЛНЯЕТСЯ!
.endif
Xor EAX,EAX
Ret 16
WndProc1 EndP
Так вот код, который должен выполнятся при завершении - не выполняется. Пробовал писать в лог все приходящие сообщения, и обнаружил, что WM_QUERYENDSESSION вообще не регистрируется... Что не так?
Спасибо!
Питерский2 вне форума Ответить с цитированием
Старый 18.06.2014, 09:50   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,331
По умолчанию

1) Message only окна НЕ получают бродкасты.
2) Если вы создаете message only окно, зачем присваивать ему имя?
3) Если вы создаете message only окно, зачем пытаетесь его отобразить?
4) Все необработанные сообщения должны передаваться в DefWindowProc.
waleri вне форума Ответить с цитированием
Старый 18.06.2014, 19:20   #3
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

Бэкапер или... резервирование данных при выключении ПК. - DGT, Астана, 2010, №3, с.46:
Код:
//------------------------------------------
// Backup & Copy
// Модуль резервного копирования данных при выключении компа
// Author: Бадло Сергей Григорьевич
// H-page: http://raxp.radioliga.com
// Cистемные требования: WinOS
//------------------------------------------

program backup_copy;

uses  Messages, Classes, Windows, sysutils, to_tray;

type
  TFNTimeCallBack = procedure(uTimerID, uMessage: UINT;
    dwUser, dw1, dw2: DWORD) stdcall;

  PDevBroadcastHdr = ^TDevBroadcastHdr;
  TDevBroadcastHdr = packed record
  dbcd_size: DWORD;
  dbcd_devicetype: DWORD;
  dbcd_reserved: DWORD;
 end;

  PDevBroadcastVolume = ^TDevBroadcastVolume;
  TDevBroadcastVolume = packed record
  dbcv_size: DWORD;
  dbcv_devicetype: DWORD;
  dbcv_reserved: DWORD;
  dbcv_unitmask: DWORD;
  dbcv_flags: Word;
 end;

 TF = class
 protected
  FWnd: HWnd;
  constructor Create;
  destructor Destroy;

  procedure WndProcc(var Msg:TMessage); message WM_DeviceChange;
  procedure WMQueryEndSession(var Msg : TWMQueryEndSession); message WM_QueryEndSession;
end;


const
  WinTitle = 'TBackup';

  DBT_DeviceArrival = $8000;
  DBT_DeviceRemoveComplete = $8004;
  DBTF_Media = $0001;
  DBT_DevTyp_Volume = $0002;

var
  FWnd: HWnd;
  //
  Handle: HWND;
  WinClass: TWndClass;
  Msg: tmsg;
  hint: shortstring = 'Backup';
  status: string = '...чего-то хотел?';
  id, id2: integer;
  gl_exit, on_off: boolean;

  t: tf;
  pn: string;
  fl: textfile;

  //таймер-
  tmr2: integer;
  function timeSetEvent(uDelay, uResolution: UINT;lpFunction: TFNTimeCallBack; dwUser: DWORD; uFlags: UINT): UINT;stdcall; external 'winmm.dll' name 'timeSetEvent';
  function timeKillEvent(uTimerID: UINT): UINT; stdcall; external 'winmm.dll' name 'timeKillEvent';


//выруб компа -------------------------------------------
function GetWinVersion:String;//версия wind-ы
var VersionInfo:TOSVersionInfo;
    OSName:String;
begin
 //устанавливаем размер записи
 VersionInfo.dwOSVersionInfoSize:=SizeOf(TOSVersionInfo );
 if Windows.GetVersionEx(VersionInfo) then
  begin
   with VersionInfo do
    begin
     case dwPlatformId of
      VER_PLATFORM_WIN32s:OSName:='Win32s';
      VER_PLATFORM_WIN32_WINDOWS:OSName:='98';
      VER_PLATFORM_WIN32_NT:OSName:='Windows NT';
     end; //case dwPlatformId*
     Result:=OSName;
    end;  //with VersionInfo*
  end else Result:=''
end;

procedure off;
const SE_SHUTDOWN_NAME = 'SeShutdownPrivilege';
var   hToken:THandle;
      tkp:TTokenPrivileges;
      tkpo:TTokenPrivileges;
      zero:DWORD;
begin
 if not on_off then begin
  on_off:= true; //триггер- (искл. множ.вызовы)
  //
  if Pos('Windows NT',GetWinVersion)=1 then
   begin
    zero:= 0;
    //
    if not OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,hToken) then Exit;
    if not OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then Exit;
    //SE_SHUTDOWN_NAME*
    if not LookupPrivilegeValue( nil,'SeShutdownPrivilege' ,tkp.Privileges[0].Luid) then Exit;
    //
    tkp.PrivilegeCount:=1;
    tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges(hToken,False,tkp,SizeOf(TTokenPrivileges),tkpo,zero);
    if Boolean(GetLastError()) then Exit
     else ExitWindowsEx(EWX_FORCE or EWX_SHUTDOWN,0);
   end else ExitWindowsEx(EWX_FORCE or EWX_SHUTDOWN,0)
  end
end;
// end выруб компа --------------------------------------------



// таймер - иконка --------------------------------------------
procedure Ontmr2(uTimerID, uMessage: uint;dwUser, dw1, dw2: dword) stdcall;
begin
 see_tray(handle, hint,true)
end;
procedure timer_create;
begin
 tmr2:= timesetevent(100,0,@Ontmr2,0,1)
end;
procedure timer_destroy;
begin
 timeKillEvent(tmr2);
 delicon(Handle)
end;
// end таймер - иконка --------------------------------------------------------



// СКЕЛЕТ ===================================
function GetDrive(pDBVol: PDevBroadcastVolume): string;
var i: Byte;
    Maske: DWORD;
begin
 Maske := pDBVol^.dbcv_unitmask;
 for i := 0 to 25 do begin
  if (Maske and 1) = 1 then
   Result := Char(i + Ord('A')) + ':';
  Maske := Maske shr 1;
 end
end;

constructor TF.Create;
begin
 inherited Create;
 FWnd:= AllocateHWnd(WndProcc);
end;

destructor TF.Destroy;
begin
 inherited Create;
 deAllocateHWnd(fWnd)
end;
...
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 18.06.2014, 19:20   #4
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

...
Код:
procedure start_bat; // запустить с ожиданием-
var si: TStartupInfo;
    p: TProcessInformation;
begin
 with Si do begin
  cb:= SizeOf( Si);
  dwFlags:= startf_UseShowWindow;
  wShowWindow:= 5
 end;
 Createprocess(nil,pchar(pn),nil,nil ,false,Create_default_error_mode,nil,nil,si,p);
 WaitForSingleObject(p.hProcess,INFINITE);
 CloseHandle(p.hProcess);
 CloseHandle(p.hThread)
end;

procedure TF.WMQueryEndSession (var Msg : TWMQueryEndSession); // перехват завершения работы-
begin
 if (not gl_exit) then begin // если первое завершение, то:
                             // сбросить завершение,
                             // скопировать - запустить батник,
                             // подождать завершения копирования,
                             // выключить самому
  message.Result:= 0;
  //gl_exit:= true;            // разрешаем дальнейшую выгрузку
  start_bat;                 // запускаем backup с ожиданием
  //off                        // выключаем машину
  //
 end else message.Result:= 1
end;


procedure tf.WndProcc(var Msg: TMessage); // перехват события USB-
begin
 if msg.WParam = DBT_DEVICEARRIVAL then
  if PDevBroadcastHdr(Msg.lParam)^.dbcd_devicetype = DBT_DevTyp_Volume then ;
   //messagebox(handle,pchar(GetDrive(PDevBroadcastVolume(Msg. lParam))),'',0);
end;

function WndProc(hnd, wmsg, wparam, lparam: integer): integer; stdcall;
begin
 case wmsg of
  //
  WM_HOTKEY: begin
              if lo(wparam)= 34 then begin start_bat; status:= 'резервное копирование выполнено!' end;
              if lo(wparam)= 38 then begin off;       status:= '...выключаем все.' end;
             end;
  TRAY_CALLBACK: case dword(lparam) of
           {WM_LBUTTONdblCLK: begin
                              UnRegisterHotKey(handle,id);
                              PostQuitMessage(handle);
                              timer_destroy;
                              closeWindow(Handle)
                             end;}
           WM_MBUTTONDOWN  : begin  
                              UnRegisterHotKey(handle,id);
                              PostQuitMessage(handle);
                              timer_destroy;
                              closeWindow(Handle)
                             end;
           WM_LBUTTONDOWN  : hint:= 'Вау!';
           WM_LBUTTONUP    : begin
                              hint:= 'Backup';
                              show_tn(1,status,'Backup files in Windows exit, RAMEDIA Inc.')
                             end;
           WM_RBUTTONUP    : show_tn(1,'• осуществить backup сейчас <Shift>+<1>'#10+
                                       '• выключить машину <Shift>+<2>'#10+
                                       '• закрыть утилиту средней кнопкой'#10#10+
                                       '-----------------------------------------------------'#10+
                                       'Разработчик:  Бадло Сергей Григорьевич'#10+
                                       'http://raxp.radioliga.com','Backup files in Windows exit, RAMEDIA Inc.');

          end;

  WM_DESTROY: begin
               PostQuitMessage(0);
               timer_destroy
              end;
  else Result:= DefWindowProc(hnd, wmsg, wparam, lparam);
 end
end;

procedure CreateMySelf;
begin
 with WinClass do begin
  lpszClassName:= WinTitle;
  lpfnWndProc  := @WndProc;
  cbClsExtra   := 0;
  cbWndExtra   := 0;
  hInstance    := hInstance
 end;

 RegisterClass(WinClass);
 Handle:= CreateWindowEx(WS_EX_WINDOWEDGE, WinTitle, 'API', WS_MINIMIZE, integer(CW_USEDEFAULT), integer(CW_USEDEFAULT), 0, 0, 0, 0, hInstance, nil)
end;

begin
 //создаем bat- ник если потерялся :)
 pn:= ExtractFilePath(paramstr(0))+ 'copy.bat';
 if not fileexists(pn) then begin
  AssignFile(fl, pn);
  ReWrite(fl);
  writeln(fl, 'xcopy "c:\1\*.*" "c:\backup\*.*"');
  writeln(fl, 'rem xcopy c:\источник\* \\другойкомпьютер\шара\ /D /Y');
  CloseFile(fl)
 end;

 t:= tf.Create;
 CreateMySelf;
 timer_create;
 //
 id:=GlobalAddAtom('hotkey1');
 RegisterHotKey(handle, id, MOD_CONTROL, ord('1'));
 id2:=GlobalAddAtom('hotkey2');
 RegisterHotKey(handle, id2, MOD_CONTROL, ord('2'));

 try while GetMessage(Msg, 0, 0, 0) do begin
  TranslateMessage(Msg);
  DispatchMessage(Msg)
 end finally t.destroy end
// END СКЕЛЕТ ================

end.
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 06.10.2014, 11:48   #5
Питерский2
Пользователь
 
Регистрация: 20.05.2014
Сообщений: 29
По умолчанию

Ага, разобрался, всем спасибо!!!
Питерский2 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Событие Worksheet_Change не "ловится" на неактивном листе... Олег* Microsoft Office Excel 4 08.01.2010 00:43