' ########################################################################################
' Microsoft Windows
' File: CW_Button_01.bas
' Contents: CWindow - Button
' Compiler: FreeBasic 32 & 64 bit
' Copyright (c) 2025 José Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#define UNICODE
#INCLUDE ONCE "AfxNova/CWindow.inc"
USING AfxNova
DECLARE FUNCTION wWinMain (BYVAL hInstance AS HINSTANCE, _
BYVAL hPrevInstance AS HINSTANCE, _
BYVAL pwszCmdLine AS WSTRING PTR, _
BYVAL nCmdShow AS LONG) AS LONG
END wWinMain(GetModuleHandleW(NULL), NULL, wCommand(), SW_NORMAL)
' // Forward declaration
DECLARE FUNCTION WndProc (BYVAL hwnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT
' ========================================================================================
' Main
' ========================================================================================
FUNCTION wWinMain (BYVAL hInstance AS HINSTANCE, _
BYVAL hPrevInstance AS HINSTANCE, _
BYVAL pwszCmdLine AS WSTRING PTR, _
BYVAL nCmdShow AS LONG) AS LONG
' // Set process DPI aware
SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE)
' // Enable visual styles without including a manifest file
AfxEnableVisualStyles
' // Creates the main window
DIM pWindow AS CWindow = "MyClassName" ' Use the name you wish
DIM hWin AS HWND = pWindow.Create(NULL, "CWindow - Button", @WndProc)
' // Sizes it by setting the wanted width and height of its client area
pWindow.SetClientSize(400, 220)
' // Centers the window
pWindow.Center
' // Adds a button
pWindow.AddControl("Button", hWin, IDCANCEL, "&Close", 270, 155, 75, 30)
' // Anchors the button to the bottom and the right side of the main window
pWindow.AnchorControl(IDCANCEL, AFX_ANCHOR_BOTTOM_RIGHT)
' // Displays the window and dispatches the Windows messages
FUNCTION = pWindow.DoEvents(nCmdShow)
END FUNCTION
' ========================================================================================
' ========================================================================================
' Main window procedure
' ========================================================================================
FUNCTION WndProc (BYVAL hwnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT
SELECT CASE uMsg
' // If an application processes this message, it should return zero to continue
' // creation of the window. If the application returns –1, the window is destroyed
' // and the CreateWindowExW function returns a NULL handle.
CASE WM_CREATE
RETURN 0
' // Sent when the user selects a command item from a menu, when a control sends a
' // notification message to its parent window, or when an accelerator keystroke is translated.
CASE WM_COMMAND
SELECT CASE CBCTL(wParam, lParam)
CASE IDCANCEL
' // If ESC key pressed, close the application by sending an WM_CLOSE message
IF CBCTLMSG(wParam, lParam) = BN_CLICKED THEN SendMessageW(hwnd, WM_CLOSE, 0, 0)
END SELECT
RETURN 0
CASE WM_DESTROY
' // End the application by sending an WM_QUIT message
PostQuitMessage(0)
RETURN 0
END SELECT
' // Default processing of Windows messages
FUNCTION = DefWindowProcW(hwnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
' RAW Windows API version
#Include Once "windows.bi"
Dim Shared hWndMain As HWND
Dim Shared hButton As HWND
Function WindowProc(ByVal hWnd As HWND, ByVal uMsg As UINT, ByVal wParam As WPARAM, ByVal lParam As LPARAM) As LRESULT
Select Case uMsg
Case WM_COMMAND
If HiWord(wParam) = BN_CLICKED Then
If Cast(HWND, lParam) = hButton Then
MessageBox(hWnd, "Button clicked!", "Info", MB_OK Or MB_ICONINFORMATION)
End If
End If
Case WM_DESTROY
PostQuitMessage(0)
Return 0
End Select
Return DefWindowProc(hWnd, uMsg, wParam, lParam)
End Function
Sub WinMain()
Dim wc As WNDCLASS
Dim msg As MSG
Dim hInstance As HINSTANCE = GetModuleHandle(NULL)
Dim className As String = "MyWindowClass"
With wc
.style = CS_HREDRAW Or CS_VREDRAW
.lpfnWndProc = @WindowProc
.cbClsExtra = 0
.cbWndExtra = 0
.hInstance = hInstance
.hIcon = LoadIcon(NULL, IDI_APPLICATION)
.hCursor = LoadCursor(NULL, IDC_ARROW)
.hbrBackground = Cast(HGDIOBJ, COLOR_BTNFACE + 1)
.lpszMenuName = NULL
.lpszClassName = StrPtr(className)
End With
RegisterClass(@wc)
hWndMain = CreateWindowEx(0, className, "Pure WinAPI Window", WS_OVERLAPPEDWINDOW, _
100, 100, 400, 300, NULL, NULL, hInstance, NULL)
hButton = CreateWindowEx(0, "BUTTON", "Click Me", WS_CHILD Or WS_VISIBLE Or BS_PUSHBUTTON, _
150, 100, 100, 30, hWndMain, Cast(HMENU, 1001), hInstance, NULL)
ShowWindow(hWndMain, SW_SHOWNORMAL)
UpdateWindow(hWndMain)
While GetMessage(@msg, NULL, 0, 0)
TranslateMessage(@msg)
DispatchMessage(@msg)
Wend
End Sub
WinMain()
I'd love to understand how CWindow simplifies or abstracts this kind of setup. Does it handle message loops and control creation internally?