Create a functioning form with Windows API.

Post date: Mar 9, 2010 12:27:48 PM

Not using VCL results in a smaller executable file size. Therefore, it may be required to create a form using only Windows API calls. This well-commented example shows you how to add functionality to the form such as clicking the button for an interaction with the edit box.

program Project1;
uses
  Windows,
  Messages;
var
  WndClass: TWndClass;
  MainForm, Button1, Edit1: HWND;
  HAppInstance: integer;
  Msg: TMsg;
procedure Button1Click;
var
  EditText: array[0..255] of char;
begin
  GetWindowText(Edit1, EditText, 256);
  // Display message box
  MessageBox(MainForm,
    PChar('You typed: ' + EditText),
    'Message',
    MB_APPLMODAL OR MB_ICONINFORMATION OR MB_OK);
end;
procedure CreateControls;
var
  hControlFont: HFONT;
  lfControl: TLogFont;
begin
  // Create all controls (Edit1, Button1)
  // See the help file for a description of the style flags
  Edit1 := CreateWindowEx(WS_EX_CLIENTEDGE, // Extended style
    'EDIT', // EDIT creates an edit box
    'Edit1', // Name of window - also the text that will be in it
    WS_CHILD OR WS_VISIBLE OR ES_AUTOHSCROLL OR ES_NOHIDESEL, // style flags
    8, 16, 160, 21, // Position and size
    MainForm, // Parent window
    0, // Menu - none because it's an edit box(!)
    HAppInstance, // Application instance
    nil); // No creation data
  Button1 := CreateWindow('BUTTON', // BUTTON creates an button, obviously
    'Show Message', // Name of window - also the text that will be in it
    WS_CHILD OR WS_VISIBLE OR BS_PUSHBUTTON OR BS_TEXT, // style flags
    8, 40, 96, 25, // Position and size
    MainForm, // Parent window
    0, // Menu - none because it's a button
    HAppInstance, // Application instance
    nil); // No creation data
  // Set up the font
  { Calculate font height from point size - they are not the same thing!
    The first parameter of MulDiv is the point size. }
  lfControl.lfHeight := -MulDiv(8, GetDeviceCaps(GetDC(0), LOGPIXELSY), 96);
  lfControl.lfFaceName := 'MS Sans Serif';
  // Create the font
  hControlFont := CreateFontIndirect(lfControl);
  // Tell controls to set their fonts
  SendMessage(Edit1, WM_SETFONT, hControlFont, 1);
  SendMessage(Button1, WM_SETFONT, hControlFont, 1);
end;
function WindowProc(hwnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM):
  LRESULT; stdcall;
begin
  // This is the function Windows calls when a message is sent to the application
  case uMsg of // Check which message was sent
    WM_DESTROY: PostQuitMessage(0); // Otherwise app will continue to run
    // Handle any other messages here
    WM_ACTIVATE: SetFocus(Edit1);
    WM_COMMAND:
      begin
        Result := 0; // Default return value for this message
        if lParam = Button1 then
          case wParam of
            BN_CLICKED: Button1Click; // Button was clicked
          else Result := DefWindowProc(hwnd, uMsg, wParam, lParam);
          end; // case wNotifyCode of
      end; // case: WM_COMMAND
    // Use default message processing
    else Result := DefWindowProc(hwnd, uMsg, wParam, lParam);
  end;
end;
begin
  HAppInstance := HInstance;
  // Set up window class
  with WndClass do begin
    Style := 0;
    lpfnWndProc := @WindowProc; // See function above
    cbClsExtra := 0; // no extra class memory
    cbWndExtra := 0; // no extra window memory
    hInstance := HAppInstance; // application instance
    hIcon := 0; // use default icon
    hCursor := LoadCursor(0, IDC_ARROW); // use arrow cursor
    hbrBackground := COLOR_WINDOW; // standard window colour
    lpszMenuName := nil; // no menu resource
    lpszClassName := 'TMainForm';
  end; // with WndClass
  Windows.RegisterClass(WndClass); // Don't use Delphi's version of RegisterClass
  // Create the window
  MainForm := CreateWindow('TMainForm',
    'Delphi API Demo', // window caption
    WS_OVERLAPPEDWINDOW, // standard window style
    CW_USEDEFAULT, CW_USEDEFAULT, // default position
    320, 200, // size
    0, // no owner window
    0, // no menu
    hInstance, // application instance
    nil);
  CreateControls; // See above
  ShowWindow(MainForm, SW_SHOWNORMAL); // make window visible
  // Set up message loop
  while GetMessage(Msg, 0, 0, 0) <> BOOL(FALSE) do begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  end;
  // I'm not sure these are actually needed
  DestroyWindow(Edit1);
  DestroyWindow(Button1);
end.