delphi एफएमएक्स प्रोजेक्ट में विंडोज़ शटडाउन इवेंट को कैसे डब्लूएम_क्वेरेंस और डब्लूएमएमसीडीसीएसी के रूप में वीसीएल प्रोजेक्ट पर प्राप्त करना है?




firemonkey (2)

मुझे विंडोज बंद करना रोकना होगा, और कुछ डीबी क्वेरी निष्पादित करना होगा, इससे पहले कि मेरा आवेदन बंद हो जाएगा। मैं विंडोज 10 के तहत एक FMX परियोजना पर डेल्फी XE10 का उपयोग कर रहा हूं

मैंने जो कोशिश की वह नीचे दिया गया कोड है, लेकिन यह काम नहीं करता है

  private
    { Private declarations }
  {$IFDEF MSWINDOWS}
    procedure WMQueryEndSession(var Msg: TWMQueryEndSession); message WM_QUERYENDSESSION;
    procedure WMEndSession(var Msg : TWMQueryEndSession); message  WM_ENDSESSION ;
  {$ENDIF}

  end;



procedure TfMain.WMQueryEndSession(var Msg: TWMQueryEndSession);
var
 lista:TStringList;
begin

{$IFDEF MSWINDOWS}
  try
    lista:=TStringList.Create;
    lista.Add(FOrmatDateTime('DD/MM/YYYY HH:NN:SS',now)+' event WMQueryEndSession');
    Lista.SaveToFile(froot+formatdatetime('YYMMDDHHNNSSZZZ',now)+'.log');
    SincroClose();
    lista.Add(FOrmatDateTime('DD/MM/YYYY HH:NN:SS',now)+' Done');
    Lista.SaveToFile(froot+formatdatetime('YYMMDDHHNNSSZZZ',now)+'.log');
  finally
    lista.Free;
  end;
{$ENDIF}
  inherited;

end;



procedure TfMain.WMEndSession(var Msg: TWMQueryEndSession);
var
 lista:TStringList;
begin

{$IFDEF MSWINDOWS}
  try
    lista:=TStringList.Create;
    lista.Add(FOrmatDateTime('DD/MM/YYYY HH:NN:SS',now)+' WMEndSession');
    Lista.SaveToFile(froot+formatdatetime('YYMMDDHHNNSSZZZ',now)+'.log');
    SincroClose();
    lista.Add(FOrmatDateTime('DD/MM/YYYY HH:NN:SS',now)+' Done');
    Lista.SaveToFile(froot+formatdatetime('YYMMDDHHNNSSZZZ',now)+'.log');
  finally
    lista.Free;
  end;
{$ENDIF}
  inherited;

end;



procedure TfMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var lista:TStringList;
begin

{$IFDEF MSWINDOWS}
  CanClose:=false;
  try
    lista:=TStringList.Create;
    lista.Add(FOrmatDateTime('DD/MM/YYYY HH:NN:SS',now)+' FormCloseQuery');
    Lista.SaveToFile(froot+formatdatetime('YYMMDDHHNNSSZZZ',now)+'.log');
    SincroClose();
    lista.Add(FOrmatDateTime('DD/MM/YYYY HH:NN:SS',now)+' Done');
    Lista.SaveToFile(froot+formatdatetime('YYMMDDHHNNSSZZZ',now)+'.log');
    CanClose:=true;
  finally
    lista.Free;
  end;
{$ENDIF}

end;

केवल सामान्य बंद करने वाला आवेदन, ठीक काम करेगा, फ़ार्मक्लोसेकन ईवेंट के तहत, लेकिन जब Windows बंद हो रहा है, मेरा एप्लिकेशन कोई भी डेटा सहेजे बिना बंद हो जाएगा


FormCloseQuery कार्य करता है क्योंकि यह रूपरेखा द्वारा सामने आ गया है। जब आपका विंडोज़ बंद हो रहा है तो आपका एप्लीकेशन किसी भी डेटा को सहेजता नहीं है क्योंकि आपके संदेश संचालकों को कभी कॉल नहीं किया जाता है। संदेश हैंडलिंग केवल वीसीएल अनुप्रयोगों के लिए उपलब्ध है, एफएमएक्स अनुप्रयोगों में मैसेजिंग के रूप में दस्तावेज के लिए एक अलग तंत्र है।

संक्षिप्त विवरण यहां दर्शाता है कि एफएमएक्स फ्रेमवर्क में ओएस से सूचनाएं प्राप्त करना संभव है। हालांकि मुझे नहीं पता है कि इसमें शटडाउन नोटिफिकेशन शामिल है और यदि आपकी वापसी को सेट करना संभव है, क्योंकि दस्तावेज़ीकरण संदेश ऑब्जेक्ट को केवल पढ़ने के लिए बताता है

जब तक आप यह पता न कर लेते हैं कि एफएमएक्स मैसेजिंग तंत्र कैसे काम करता है और अगर यह आवश्यकताओं को पूरा करता है, तो आप पारंपरिक रूप से अपनी प्रपत्र की खिड़की उप-वर्ग कर सकते हैं। नीचे उदाहरण SetWindowSubclass का उपयोग करता है

...
protected
  {$IFDEF MSWINDOWS}
  procedure CreateHandle; override;
  procedure DestroyHandle; override;
  procedure WMQueryEndSession(var Msg: TWMQueryEndSession); message WM_QUERYENDSESSION;
  procedure WMEndSession(var Msg: TWMEndSession); message WM_ENDSESSION;
  {$ENDIF}
...

implementation

{$IFDEF MSWINDOWS}
uses
  FMX.Platform.Win, Winapi.Commctrl;

function SubclassProc(Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM;
  uIdSubclass: UINT_PTR; RefData: DWORD_PTR): LRESULT; stdcall;
var
  Self: TfMain;
  Message: TMessage;
begin
  Result := DefSubclassProc(Wnd, Msg, wParam, lParam);
  case Msg of
    WM_QUERYENDSESSION, WM_ENDSESSION:
    begin
      Self := TfMain(RefData);
      Message.Msg := Msg;
      Message.WParam := wParam;
      Message.LParam := lParam;
      Message.Result := Result;
      Self.Dispatch(Message);
      Result := Message.Result;
    end;
  end;
end;

procedure TfMain.CreateHandle;
var
  Wnd: HWND;
begin
  inherited;
  Wnd := WindowHandleToPlatform(Self.Handle).Wnd;
  SetWindowSubclass(Wnd, SubclassProc, 1, DWORD_PTR(Self));
end;

procedure TfMain.DestroyHandle;
var
  Wnd: HWND;
begin
  Wnd := WindowHandleToPlatform(Self.Handle).Wnd;
  RemoveWindowSubclass(Wnd, SubclassProc, 1);
  inherited;
end;

procedure TfMain.WMQueryEndSession(var Msg: TWMQueryEndSession);
begin
  // do not call inherited here, there's no inherited handling
end;

procedure TfMain.WMEndSession(var Msg: TWMEndSession);
begin
  // do not call inherited here, there's no inherited handling
end;

var
  ICC: TInitCommonControlsEx;

initialization
  ICC.dwSize := SizeOf(ICC);
  ICC.dwICC := ICC_STANDARD_CLASSES;
  InitCommonControlsEx(ICC);
{$ENDIF}

विंडोज में (अपेक्षाकृत) हालिया रिलीज में इस क्षेत्र में कई बदलाव हुए हैं - यानी विंडोज एक्सपी वापस लौट रहे हैं। इसके अलावा, जिस तरह से डेल्फी खिड़कियों को एप्लिकेशन द्वारा प्रबंधित किया जाता है, उन्हें अन्य ओएस परिवर्तनों के संबंध में बेहतर ढंग से व्यवहार करने के लिए बदल दिया गया है और चीजों को फिर से एफएमएक्स में बदल दिया गया है।

WM_QUERYENDSESSION अब केवल शीर्ष-स्तरीय विंडो में भेजा जाता है। यदि आपका ऐप्लिकेशन वीसीएल एप्लीकेशन है और इसमें MainFormOnTaskbar सेट किया गया है तो आपका एप्लिकेशन मुख्य फ़ॉर्म एक शीर्ष-स्तरीय विंडो है और आपको संदेश प्राप्त होना चाहिए। यदि MainFormOnTaskbar को गलत सेट किया गया है, या यदि आपका फ़ॉर्म मुख्य रूप (नाम के बावजूद) नहीं है, तो यह शीर्ष-स्तरीय विंडो नहीं है और संदेश प्राप्त नहीं करेगा।

यदि आपका आवेदन FMX.Platform.Win का उपयोग करता है तो आपको अपने मुख्य फार्म का अभिभावक कैसे निर्धारित किया जाता है, यह निर्धारित करने के लिए FMX.Platform.Win WindowService के चारों ओर खुदाई करने की आवश्यकता होगी। [एक्सई 4] एफएमएक्स स्रोत के निरीक्षण के आधार पर, चीजों को इस क्षेत्र में पीछे से देखा गया है (वीसीएल के सापेक्ष) और कुछ बदसूरत कोड यहाँ खुशबू आ रही हैं

ऐसी समस्याएं जो इस क्षेत्र के बेहतर कारणों से विस्टा से आगे हैं, WM_QUERYSSESSION अब बिना किसी दृश्यमान शीर्ष-स्तरीय विंडो के अनुप्रयोगों में भेजे जाते हैं। भले ही आपका मुख्य फ़ॉर्म एक शीर्ष-स्तरीय खिड़की है, अगर उस बिंदु पर दिखाई नहीं दे रहा है जो विंडोज बंद हो रहा है तो ऐसा इसलिए हो सकता है कि आपको संदेश प्राप्त नहीं हो रहा है।

यदि समस्या यह है कि आपकी विंडो आपके आवेदन में शीर्ष-स्तरीय विंडो नहीं है, तो यहां पर्याप्त जानकारी होनी चाहिए ताकि आप कम से कम यह समझ सकें कि क्यों

वीसीएल आवेदन में, अपना मुख्य फॉर्म बनाकर कार्यपट्टी विंडो को समस्या का समाधान करना चाहिए। क्या कोई एफएमएक्स आवेदन में इस मुद्दे को हल करने के लिए एक समान साधन है, मुझे नहीं पता।

यदि आपके पास एक वैध शीर्ष-स्तरीय विंडो है और समस्या यह है कि आपकी शीर्ष-स्तरीय विंडो (कभी-कभी) दिखाई नहीं दे रही है, तो आपको शटडाउन प्रक्रिया में हुक करने के लिए कुछ अन्य तंत्र खोजने की आवश्यकता होगी, लेकिन आपको पता होना चाहिए कि कोई भी व्यवहार निर्भर करता है अन्य प्रक्रियाओं को इस बात का ध्यान रखना होगा कि वे अन्य प्रक्रियाओं को बंद कर रहे हैं और उपलब्ध नहीं हो सकते हैं।

बेशक, यह सभी विंडोज़ बंद सूचनाओं के लिए बहुत विशिष्ट है यदि आप अपने एफएमएक्स आवेदन के साथ अन्य प्लेटफार्मों का समर्थन करने का इरादा रखते हैं तो आपको शटडाउन व्यवहार से अलग तरीके से निपटने की आवश्यकता होगी, यह सोचते हुए कि एफएमएक्स एक क्रॉस-प्लेटफॉर्म शटडाउन अधिसूचना समाधान प्रदान नहीं करता है (अन्यथा आप इसका उपयोग करेंगे, नहीं?)

(और यदि आप वास्तव में केवल विंडोज को लक्षित कर रहे हैं, तो धरती पर आप एफएमएक्स का उपयोग क्यों कर रहे हैं?)