program APIRegistryChanges;

uses Windows, Messages, SysUtils;

const AppName='Зміни у реєстрі';

var AMessage  : TMsg;
    hWindow   : HWnd;
    hBtnExit  : HWnd;
    hBtnReg   : HWnd;
    hList     : HWnd;

    hThread1  : THandle;
    ThreadID  : DWORD;

function ThreadFunc(Ptr: Pointer): LongInt;
var evnt : THandle;
    RK   : HKey;
    S    : string;
begin
  evnt := CreateEvent(nil, false, false, nil);
  RegOpenKeyEx(HKEY_CURRENT_USER, 'Software\IC\RegDemo', 0, KEY_READ, RK);
  RegNotifyChangeKeyValue(RK, true, REG_NOTIFY_CHANGE_LAST_SET, evnt, true);

  if WaitForSingleObject(evnt, INFINITE) = WAIT_OBJECT_0 then
  begin
    S := TimeToStr(Time) + ': У реєстр внесено зміни!';
    SendMessage(hList, LB_ADDSTRING, 0, DWORD(PChar(S)));
    MessageBox(hWindow, PWideChar(S), 'Ооо!', MB_ICONINFORMATION);
  end;

  RegCloseKey(RK);
  CloseHandle(evnt);
end;

function WindowProc(Window: HWnd; AMessage, WParam, LParam: longint): longint; stdcall; export;
var RK   : HKey;
begin
  WindowProc := 0;
  case AMessage of
    WM_DESTROY: begin PostQuitMessage(0); Exit; end;
    WM_COMMAND: if LParam = hBtnExit then begin PostQuitMessage(0); Exit; end
                  else if LParam = hBtnReg then begin
                    TerminateThread(hThread1, 0);
                    CloseHandle(hThread1);
                    hThread1 := BeginThread(nil, 0, @ThreadFunc, nil, 0, ThreadID);
                  end;
    WM_KEYDOWN: if (wParam = VK_RETURN) or (wParam = VK_ESCAPE) then SendMessage(hBtnExit, BM_CLICK, 0, 0);
  end;
  WindowProc  := DefWindowProc(Window, AMessage, WParam, LParam);
end;

function WinRegister: boolean;
var WindowClass: TWndClass;
begin
  with WindowClass do begin
    Style := CS_HREDRAW or CS_VREDRAW;
    lpfnWndProc := @WindowProc;
    cbClsExtra := 0;
    cbWndExtra := 0;
    hInstance := SysInit.HInstance;
    hIcon := LoadIcon(0, IDI_APPLICATION);
    hCursor :=  LoadCursor(0, IDC_ARROW);
    hbrBackGround := COLOR_WINDOW;
    lpszMenuName := nil;
    lpszClassName := AppName;
  end;
  Result := RegisterClass(WindowClass) <> 0;
end;

function WinCreate: HWnd;
var hWindow : HWnd;
begin
  hWindow := CreateWindow(AppName, 'Подія у реєстрі', WS_OVERLAPPEDWINDOW,
    200, 100, 510, 350, 0, 0, HInstance, nil);

  if hWindow<>0 then begin
    ShowWindow(hWindow, SW_SHOWNORMAL);
    UpdateWindow(hWindow);
    hBtnExit := CreateWindow('BUTTON', 'Вихід', WS_CHILD or BS_DEFPUSHBUTTON or WS_TABSTOP,
      280, 10, 200, 30, hWindow, 0, HInstance, nil);
    if hBtnExit <> 0 then ShowWindow(hBtnExit, SW_SHOWNORMAL);
    hBtnReg := CreateWindow('BUTTON', 'Очікування змін у реєстрі', WS_CHILD or WS_TABSTOP,
      280, 70, 200, 30, hWindow, 0, HInstance, nil);
    if hBtnReg <> 0 then ShowWindow(hBtnReg, SW_SHOWNORMAL);
    hList := CreateWindow('LISTBOX', '', WS_CHILD or WS_TABSTOP or WS_BORDER,
      10, 10, 260, 300, hWindow, 0, HInstance, nil);
    if hList <> 0 then ShowWindow(hList, SW_SHOWNORMAL);
  end;
  Result := hWindow;
end;

begin
  if not WinRegister then begin
    MessageBox(0, 'Клас вікна не зареєстровано', AppName, MB_OK);
    Exit;
  end;
  hWindow := WinCreate;
  if hWindow = 0 then begin
    MessageBox(0, 'Не вийшло створити вікно.', AppName, MB_OK);
    Exit;
  end;

  while GetMessage(AMessage,0,0,0) do begin
    TranslateMessage(AMessage);
    DispatchMessage(AMessage);
  end;

  CloseHandle(hThread1);
  Halt(AMessage.wParam);
end.
