Well it's completely different in Linux and Windows. In Windows you use the WinAPI or MFC, and in linux you use...well, I have no clue.
Yes, C is a procedural language, but you can still make Event-Driven UI's in it because (at least in WinAPI) the OS sends messages to the application, and when you intercept those messages, you take whatever action is neccessary...ex:
Every time you get a WM_SIZE message you will most likely want to resize all of the controls on your window, so you catch that message and resize all of the controls during it.
The simplest working Windows UI app I can think of would be:
Code:
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR pszCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
wc.cbSize=sizeof(WNDCLASSEX);
wc.style=CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc=WndProc;
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.hInstance=hInstance;
wc.hIcon=LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor=LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName=NULL;
wc.lpszClassName="TutClass";
wc.hIconSm=NULL;
RegisterClassEx(&wc);
hwnd=CreateWindowEx(0, "TutClass", "Hi!",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT WINAPI WndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch(uMsg)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
TextOut(hdc, 0, 0, "Hello, World!", 13);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam,lParam);
}
I wrote a tutorial on it a while ago if you'd like the link...