5
Haskell version of "Hello, World" using the Win32 library.
6
Demonstrates how the Win32 library can be put to use.
8
Works with Hugs and GHC. To compile it up using the latter,
9
do: "ghc -o main hello.lhs -syslib win32 -fglasgow-exts"
13
ghc -package win32 hello.lhs -o hello.exe -optl "-Wl,--subsystem,windows"
16
module Main(main) where
18
import qualified Graphics.Win32
19
import qualified System.Win32.DLL
20
import qualified System.Win32.Types
21
import Control.Exception (bracket)
27
Toplevel main just creates a window and pumps messages.
28
The window procedure (wndProc) we pass in is partially
29
applied with the user action that takes care of responding
30
to repaint messages (WM_PAINT).
35
Graphics.Win32.allocaPAINTSTRUCT $ \ lpps -> do
36
hwnd <- createWindow 200 200 (wndProc lpps onPaint)
40
OnPaint handler for a window - draw a string centred
43
onPaint :: Graphics.Win32.RECT -> Graphics.Win32.HDC -> IO ()
44
onPaint (_,_,w,h) hdc = do
45
Graphics.Win32.setBkMode hdc Graphics.Win32.tRANSPARENT
46
Graphics.Win32.setTextColor hdc (Graphics.Win32.rgb 255 255 0)
48
| otherwise = ((h-10) `div` 2)
50
| otherwise = (w-50) `div` 2
51
Graphics.Win32.textOut hdc x y "Hello, world"
55
Simple window procedure - one way to improve and generalise
56
it would be to pass it a message map (represented as a
57
finite map from WindowMessages to actions, perhaps).
61
wndProc :: Graphics.Win32.LPPAINTSTRUCT
62
-> (Graphics.Win32.RECT -> Graphics.Win32.HDC -> IO ()) -- on paint action
63
-> Graphics.Win32.HWND
64
-> Graphics.Win32.WindowMessage
65
-> Graphics.Win32.WPARAM
66
-> Graphics.Win32.LPARAM
67
-> IO Graphics.Win32.LRESULT
68
wndProc lpps onPaint hwnd wmsg wParam lParam
69
| wmsg == Graphics.Win32.wM_DESTROY = do
70
Graphics.Win32.sendMessage hwnd Graphics.Win32.wM_QUIT 1 0
72
| wmsg == Graphics.Win32.wM_PAINT && hwnd /= nullPtr = do
73
r <- Graphics.Win32.getClientRect hwnd
74
paintWith lpps hwnd (onPaint r)
77
Graphics.Win32.defWindowProc (Just hwnd) wmsg wParam lParam
79
createWindow :: Int -> Int -> Graphics.Win32.WindowClosure -> IO Graphics.Win32.HWND
80
createWindow width height wndProc = do
81
let winClass = Graphics.Win32.mkClassName "Hello"
82
icon <- Graphics.Win32.loadIcon Nothing Graphics.Win32.iDI_APPLICATION
83
cursor <- Graphics.Win32.loadCursor Nothing Graphics.Win32.iDC_ARROW
84
bgBrush <- Graphics.Win32.createSolidBrush (Graphics.Win32.rgb 0 0 255)
85
mainInstance <- System.Win32.DLL.getModuleHandle Nothing
86
Graphics.Win32.registerClass
87
( Graphics.Win32.cS_VREDRAW + Graphics.Win32.cS_HREDRAW
95
w <- Graphics.Win32.createWindow
97
"Hello, World example"
98
Graphics.Win32.wS_OVERLAPPEDWINDOW
99
Nothing Nothing -- leave it to the shell to decide the position
100
-- at where to put the window initially
103
Nothing -- no parent, i.e, root window is the parent.
104
Nothing -- no menu handle
107
Graphics.Win32.showWindow w Graphics.Win32.sW_SHOWNORMAL
108
Graphics.Win32.updateWindow w
111
messagePump :: Graphics.Win32.HWND -> IO ()
112
messagePump hwnd = Graphics.Win32.allocaMessage $ \ msg ->
114
Graphics.Win32.getMessage msg (Just hwnd)
115
`catch` \ _ -> exitWith ExitSuccess
116
Graphics.Win32.translateMessage msg
117
Graphics.Win32.dispatchMessage msg
121
paintWith :: Graphics.Win32.LPPAINTSTRUCT -> Graphics.Win32.HWND -> (Graphics.Win32.HDC -> IO a) -> IO a
122
paintWith lpps hwnd p =
124
(Graphics.Win32.beginPaint hwnd lpps)
125
(const $ Graphics.Win32.endPaint hwnd lpps)