Наверное многие заметили, что событие onActivate формы ведет себя по странному, иногда происходит его активация просто при приобретении формой фокуса, а иногда событие происходит только в случае, когда форма становится видимой?

Виной тому виндовые API. Помните начиная с 98 виндов возникла фича - когда активация окна приводит к мельканию заголовка в таскбаре. Под win95/NT4 событие формы onActivate происходит только в момент показа формы (Show, ShowModal), а в остальных осях может возникать и просто при попадании фокуса на форму (уж не знаю почему, но не всегда). Есть хороший способ избавиться от такого поведения и заставить это событие возникать только 1 раз при активации формы и в дальнейшем только тогда когда это нужно.

 

Следующий пример запрещает кнопку закрытия (и пункт "закрыть" (close) в системном меню) нужного нам окна (в данном случае Notepad).

       Очень часто мы сталкиваемся с проблемой, когда наша программа будучи запущенная в фоне и/или свёрнутая, например, в панель задач должна что-то сделать, когда Windows выключается, перезагружается или просто меняется пользователь.

       Если мы не будем отслеживать такую ситуацию, то в худшем случае у нас могут просто потеряться какие-либо данные или Windows просто не сможет выполнить перезагрузку до конца. Ей будет мешать наша программа. Не нужно думать, что Windows перед перезагрузкой рассылает приложениям сообщения о закрытии, так чтобы у тех выпаолнились обработчкики TForm.onCloseQuery/onClose.

ОС Windows отсылает перед перезагрузкой, выключением или сменой пользователя сообщения WM_QUERYENDSESSION, а потом по его успешному завершению WM_ENDSESSION. Наше приложение должно поймать эти сообщения и отреагировать так чтобы дать понять, что мы согласны перезагружаться. В частности на сообщение WM_QUERYENDSESSION мы должны вернуть не 0:

 

Устройство Windows. Процессы, потоки и функции ShellExecute и WinExec. Часть 1.

    По просьбам общественности и была написана эта статья.

Действительно невозможно профессионально разрабатывать многопоточные программы,

не зная, что такое процессы, потоки, нити и синхронизация (надеюсь посвятить этому одну из следующих статей) и,

не представляя, как они работают. В статье за основу взята операционная система Windows 2000.

Так же в этой статье будут подробно рассмотрены различные методы запуска новых процессов (программ).

 

Code:

Function ExecuteFile(FileName, Params, WorkingDir:string; Wait:boolean):integer;

{©Drkb v.3®Vit (Vitaly Nevzorov) -}

var

buffer: array[0..511] of Char;

TmpStr: String;

i: Integer;

StartupInfo:TStartupInfo;

ProcessInfo:TProcessInformation;

ext, key, fname, path:string;

exitcode:cardinal;

begin

if WorkingDir<>'' then ChDir(WorkingDir);

ext:=lowercase(ExtractFileExt(FileName));

path:=ExtractFilePath(FileName);

if ext<>'.exe' then

   With TRegistry.create do

     try

       RootKey:=HKEY_CLASSES_ROOT;

       OpenKey(ext, false);

       Key:=ReadString('');

       CloseKey;

       OpenKey(key+'\Shell\open\command', false);

       key:=ReadString('');

       fname:=ExtractFileName(key);

       if pos('/', fname)>0 then fname:=copy(fname,1, pos('/',fname)-1);

       FName:=StringReplace(FName, '%1', '', [rfReplaceAll, rfIgnoreCase]);

       if pos(' ',FileName)>0 then FileName:='"'+Filename+'"';

       TmpStr:=ExtractFilePath(key)+Fname+' '+FileName;

       if Params<>'' then TmpStr := TmpStr + ' ' + Params;

       Closekey;

     finally

       free;

     end

else

   begin

     TmpStr := FileName;

     TmpStr := TmpStr + ' ' + Params;

   end;

StrPCopy(buffer,TmpStr);

FillChar(StartupInfo,Sizeof(StartupInfo),#0);

StartupInfo.cb := Sizeof(StartupInfo);

StartupInfo.dwFlags := STARTF_USESHOWWINDOW;

StartupInfo.wShowWindow := SW_SHOWNORMAL;

if CreateProcess(nil, buffer, nil, nil, false, CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then

   begin

     if Wait then

       begin

         while WaitforSingleObject(ProcessInfo.hProcess,200)=WAIT_TIMEOUT         do application.ProcessMessages;

         GetExitCodeProcess(ProcessInfo.hProcess, exitcode);

       end;

   end

else

   Result := GetLastError();

end;

 

 

Я провел небольшое исследование, и вот что я выяснил:

При закрытии приложения (используя системное меню или вызывая метод закрытия формы), возникают следующие события:

FormCloseQuery - действие по умолчанию, устанавливает переменную CanClose в значание TRUE и продолжает закрытие формы.

FormClose

FormDestroy

Если приложение активно и вы пытаетесь завершить работу Windows (Shut Down), происходят следующие события (с соблюдением последовательности):

FormCloseQuery

FormDestroy

 

Code:

Var

  exInfo: TShellExecuteInfo;

Begin

  FillChar( exInfo, Sizeof(exInfo), 0 );

  With exInfo Do Begin

    cbSize:= Sizeof( exInfo ); // required!

    fMask := SEE_MASK_NOCLOSEPROCESS;

    Wnd   := Handle;  // forms handle

    lpVerb:= 'paintto';

    lpFile:= Pchar( pdffilename );

    lpParameters := PChar( printernameAndPort );

    nShow := SW_HIDE;

  End;

  If ShellExecuteEx( @exInfo ) Then Begin

     While GetExitCodeProcess( exinfo.hProcess, exitcode )

           and (exitcode = STILL_ACTIVE)

     Do

       Sleep( 500 );

     CloseHandle( exinfo.hProcess );

     DeleteFile( pdffilename );

  End

  Else

    ShowMessage(SysErrorMessage( GetLastError ));

 

Как мне завершить все работающие задачи?

 Ниже приведен код, который поможет вам завершить ВСЕ задачи без всяких уведомлений о необходимости сохранения данных.

 Поэтому, прежде чем запустить этот код, убедитесь в наличии сохраненных данных и в том, что пользователь осведомлен об этой операции.

 

Code:

program winmin;

 

uses

windows,

messages;

var   wc : TWndClassEx;

MainWnd : HW   Mesg : TMsg;  

 

function WindowProc(wnd:HWND; Msg : Integer; Wparam:Wparam;

Lparam:Lparam):Lresult;

stdcall;

Begin

case msg of

wm_destroy :

Begin

postquitmessage(0); exit;

Result:=0;

End;

 

else Result:=DefWindowProc(wnd,msg,wparam,lparam);

end;

 

End;

var xPos,yPos,nWidth,nHeight : Integer;

begin

wc.cbSize:=sizeof(wc);

wc.style:=cs_hredraw or cs_vredraw;

wc.lpfnWndProc:=@WindowProc;

wc.cbClsExtra:=0;

wc.cbWndExtra:=0;

wc.hInstance:=HInstance;

wc.hIcon:=LoadIcon(0,idi_application);

wc.hCursor:=LoadCursor(0,idc_arrow);

wc.hbrBackground:=COLOR_BTNFACE+1;

wc.lpszMenuName:=nil;

wc.lpszClassName:='WinMin : Main';

 

RegisterClassEx(wc);

xPos:=100;

yPos:=150;

nWidth:=400;

nHeight:=250;

 

MainWnd:=CreateWindowEx(

0,             

'WinMin : Main',

'Win Min',       

ws_overlappedwindow,

xPos,

yPos,

nWidth,  

nHeight,       

0,              

0,                 

Hinstance,         

nil                

);

 

 ShowWindow(Mai! nWnd,CmdShow);

While GetMessage(Mesg,0,0,0) do

begin

TranslateMessage(Mesg);

DispatchMessage(Mesg);

end;

 

end.

  

 

Включение, приминение и отключения привилегии. Для примера возьмем привилегию отладки приложений 'SeDebugPrivilege'

необходимую для завершения ЛЮБЫХ процессов в системе (завершение процесов созданных текущим пользователем привилегия не нужна.

Название добавление/удаление привилгии немного неправильные.  Привилегия или есть в токене процесса или ее нет. Если привилегия есть, то она может быть в

двух состояниях - или включеная или отключеная. И в этом примере мы только включаем или выключаем необходимую привилегию, а не добавляем ее.

 

Code:

{

In der Projekt Datei (.dpr):

In your project's file (.dpr):

}

 

uses

  Forms, Sysutils, Dialogs,

  MyProgr in my_prog1.pas {Form1};

 

const

  email = Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.';

  homepage = 'http://www.myhomepage.com';

 

// Gultigkeit auf 21. April begrenzen.

 

YearExp = 2003;

  MonthExp = 4;

  DayExp = 21;

 

function CheckDate(y, m, d: Integer): Boolean;

begin

  Result := True;

  if (Date > EncodeDate(y, m, d)) then

  begin

    ShowMessage('End of usage exceeded. Download a new'+

                 'version at' + ^j + homepage+ ^j + ' or contact: ' + email);

  Result := False;

  // halt;

end;

 

end;

 

 

{$R *.RES}

 

begin

  if CheckDate(YearExp, MonthExp, DayExp) then

  begin

    Application.Initialize;

    Application.Title := 'Some Title';

    Application.CreateForm(TForm1, Form1);

    Application.Run;

  end;

 

end.