Форум программистов, компьютерный форум, киберфорум
Haskell
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
Модератор
 Аватар для Curry
5158 / 3482 / 536
Регистрация: 01.06.2013
Сообщений: 7,550
Записей в блоге: 9

Оконное приложение на чистом Win API

03.06.2015, 20:46. Показов 1501. Ответов 1
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Один японец сделал, ради демки, оконное приложение на чистом Win API. Win API совсем не функциональное, и в нём есть сложность, связанная с передачей изменяемого состояния. Все действия обрабатываются оконной процедурой (callback-ом, устанавливаемым при создании окна). Так вот, он придумал весьма функциональный подход - при изменении внутреннего состояния программы (для простоты, там просто счётчик), он, каждый раз, заменяет оконную процедуру передавая счётчик через замыкание.

Оно, конечно, функционально весьма, но, мне не нравится такое обращение с Win API. В общем, его идею я изложил, в программе исправил кое чего, в разных местах, чтобы компилировалось без предупреждений. А потом и эту новаторскую идею убрал. Заменил на обычную мутабельную ссылку IORef. Стало пошустрее.
Погрызенный мной исходник:
Кликните здесь для просмотра всего текста
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
module Main where
-- Original code from: [url]http://d.hatena.ne.jp/Otter_O/20090217/1234861028[/url]
 
import System.Win32.Types
import System.Win32.DLL
import Graphics.Win32
import Data.List (unfoldr)
import Data.Int (Int32)
import Data.Maybe
import Control.Monad
import Control.Arrow
import Data.IORef
 
foreign import stdcall "PostQuitMessage" 
   postQuitMessage :: Int32 -> IO ()
 
type Vector = [Float]
type Matrix = [ [Float] ]
 
transform :: Matrix -> Vector -> Vector
transform mx v = [ mul r v| r <- mx]
 where
  mul rs cs = sum $ zipWith ( * ) rs cs
 
mxRotXZ :: Float -> Matrix
mxRotXZ rot = [ [cos rot, 0, (-1) * sin rot ],
             [0,       1,             0 ],
             [sin rot, 0,       cos rot ] ]
 
proj :: Vector -> Vector
proj ~(x: y: z: _) = [x * fac, y * fac]
 where
  fac = (z - zvp) / (zvf - zvp)
  zvp = -4 :: Float
  zvf = -1 :: Float
 
cube :: [Vector]
cube =  [ [1,  1,  1], [1, -1,  1], [-1, -1,  1], [-1,  1,  1],
  [1,  1, -1], [1, -1, -1], [-1, -1, -1], [-1,  1, -1],
  [1,  1,  1], [1,  1, -1], [-1,  1, -1], [-1,  1,  1],
  [1, -1,  1], [1, -1, -1], [-1, -1, -1], [-1, -1,  1] ]
 
toMaybe :: Bool -> a -> Maybe a
toMaybe p a
 | p = Just a
 | otherwise = Nothing
 
varMap :: ( [a] -> (b, [a] ) ) -> [a] -> [b]
varMap f = unfoldr (uncurry toMaybe . (not.null &&& f) )
 
main :: IO ()
main = do
 let clsName    =  mkClassName "My Window Class"
 hinst      <- getModuleHandle Nothing
 whiteBrush <- getStockBrush wHITE_BRUSH
 curArrow   <- loadCursor Nothing iDC_ARROW
 mAtom      <- registerClass
  (cS_DBLCLKS, 
  hinst,        -- HINSTANCE
  Nothing,  -- Maybe HICON
  Just curArrow,    -- Maybe HCURSOR
  Just whiteBrush,-- Maybe HBRUSH
  Nothing,  -- Maybe LPCTSTR
  clsName)
 
 iRf <- newIORef 0
 
 when (isJust mAtom) $ do
  hwnd <- createWindow 
   clsName
   "Rotating Box Demo" 
   (wS_THICKFRAME + wS_CAPTION + wS_SYSMENU) 
   Nothing 
   Nothing 
   Nothing 
   Nothing 
   Nothing 
   Nothing 
   hinst
   (wndProc iRf)
 
  _ <- setWinTimer hwnd 0{-tid-} 50{-msec-}
 
  _ <- showWindow hwnd sW_SHOWNORMAL
  updateWindow hwnd
  allocaMessage pump
 
  unregisterClass clsName hinst
 
pump :: LPMSG -> IO ()
pump lpmsg = do
 fContinue <- getMessage lpmsg Nothing
 when fContinue $ do
  _ <- translateMessage lpmsg
  _ <- dispatchMessage lpmsg
  pump lpmsg
 
drawBox4 :: HDC -> [ [Int32] ] -> IO ()
drawBox4 hdc ~[ [x1, y1], [x2, y2], [x3, y3], [x4, y4] ] =
 moveToEx hdc x1 y1 >>
 lineTo   hdc x2 y2 >>
 lineTo   hdc x3 y3 >>
 lineTo   hdc x4 y4 >>
 lineTo   hdc x1 y1
 
drawCube :: HDC -> Matrix -> IO ()
drawCube hdc rot = mapM_ (drawBox4 hdc) $ 
 varMap (splitAt 4) $ 
 map ( 
  (map $ ( + 400).round.( * 100) ) . proj . transform rot)
  cube
 
render :: HWND -> HDC -> Int -> IO ()
render _ hdc = drawCube hdc . rot . fromIntegral
 where
  rot :: Float -> Matrix
  rot x = mxRotXZ $ pi * x/ 180
 
onTimer :: HWND -> IORef Int -> IO ()
onTimer hwnd iRf = do
    invalidateRect (Just hwnd) Nothing True
    modifyIORef' iRf $ \i -> (i + 2) `mod` 360
 
wndProc :: IORef Int -> HWND -> WindowMessage -> WPARAM ->
  LPARAM -> IO LRESULT
wndProc iRf hwnd wm wp lp
  | wm == wM_KEYDOWN    = doFinish
  | wm == wM_LBUTTONDOWN    = doFinish
  | wm == wM_DESTROY    = killTimer (Just hwnd) 0 >> 
               postQuitMessage 0 >> return 0
  | wm == wM_SIZE   = doInvalRender
  | wm == wM_PAINT      = onPaint
  | wm == wM_TIMER  = onTimer hwnd iRf >> return 0
  | otherwise      = defWindowProc (Just hwnd) wm wp lp
  where
    doFinish = sendMessage hwnd wM_CLOSE 1 0 >> return 0
    doInvalRender = do
         invalidateRect (Just hwnd) Nothing True
         return 0
    onPaint     = allocaPAINTSTRUCT $ \ lpps -> do
     hdc <- beginPaint hwnd lpps
     i <- readIORef iRf
     render hwnd hdc i
     endPaint hwnd lpps
     return 0

И win32test.cabal
Кликните здесь для просмотра всего текста
name: win32test
version: 0.1.0.0
synopsis: test
-- description:
-- license:
license-file: LICENSE
author: KolodeznyDiver
maintainer: none@mail.ru
-- copyright:
category: Testing
build-type: Simple
-- extra-source-files:
cabal-version: >=1.10

executable win32test
main-is: Main.hs
GHC-Options: -Wall -optl-mwindows
--subsystem,windows
-- other-modules:
-- other-extensions:
build-depends: base >=4.8 && <4.9
, Win32
hs-source-dirs: src
default-language: Haskell2010
- то есть не используются никакие дополнительные пакеты, кроме входящих в дистрибутив ghc. Я использую ghc 7.10.1. Для более старых, может понадобится другой диапазон версий пакета base указать. Хотя, в коде, врят ли что менять понадобится.

p.s. Я знаю что с платформой haskell идёт обёртка для GLUT. А ещё wxHaskell есть. И с ними может короче получиться. Но, тут используется минимальное кол-во пакетов и никаких сторонних библиотек.

p.p.s. Интересно было бы глянуть на оконное приложение низкого уровня для "иксов".

Добавлено через 4 минуты
Хм. Код вставился как то очень криво. Не знаю почему так. Повторяю:
Кликните здесь для просмотра всего текста
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
module Main where
-- Original code from: [url]http://d.hatena.ne.jp/Otter_O/20090217/1234861028[/url]
 
import System.Win32.Types
import System.Win32.DLL
import Graphics.Win32
import Data.List (unfoldr)
import Data.Int (Int32)
import Data.Maybe
import Control.Monad
import Control.Arrow
import Data.IORef
 
foreign import stdcall "PostQuitMessage" 
   postQuitMessage :: Int32 -> IO ()
 
type Vector = [Float]
type Matrix = [ [Float] ]
 
transform :: Matrix -> Vector -> Vector
transform mx v = [ mul r v| r <- mx]
 where
  mul rs cs = sum $ zipWith ( * ) rs cs
 
mxRotXZ :: Float -> Matrix
mxRotXZ rot = [ [cos rot, 0, (-1) * sin rot ],
             [0,       1,             0 ],
             [sin rot, 0,       cos rot ] ]
 
proj :: Vector -> Vector
proj ~(x: y: z: _) = [x * fac, y * fac]
 where
  fac = (z - zvp) / (zvf - zvp)
  zvp = -4 :: Float
  zvf = -1 :: Float
 
cube :: [Vector]
cube =  [ [1,  1,  1], [1, -1,  1], [-1, -1,  1], [-1,  1,  1],
  [1,  1, -1], [1, -1, -1], [-1, -1, -1], [-1,  1, -1],
  [1,  1,  1], [1,  1, -1], [-1,  1, -1], [-1,  1,  1],
  [1, -1,  1], [1, -1, -1], [-1, -1, -1], [-1, -1,  1] ]
 
toMaybe :: Bool -> a -> Maybe a
toMaybe p a
 | p = Just a
 | otherwise = Nothing
 
varMap :: ( [a] -> (b, [a] ) ) -> [a] -> [b]
varMap f = unfoldr (uncurry toMaybe . (not.null &&& f) )
 
main :: IO ()
main = do
 let clsName    =  mkClassName "My Window Class"
 hinst      <- getModuleHandle Nothing
 whiteBrush <- getStockBrush wHITE_BRUSH
 curArrow   <- loadCursor Nothing iDC_ARROW
 mAtom      <- registerClass
  (cS_DBLCLKS, 
  hinst,        -- HINSTANCE
  Nothing,  -- Maybe HICON
  Just curArrow,    -- Maybe HCURSOR
  Just whiteBrush,-- Maybe HBRUSH
  Nothing,  -- Maybe LPCTSTR
  clsName)
 
 iRf <- newIORef 0
 
 when (isJust mAtom) $ do
  hwnd <- createWindow 
   clsName
   "Rotating Box Demo" 
   (wS_THICKFRAME + wS_CAPTION + wS_SYSMENU) 
   Nothing 
   Nothing 
   Nothing 
   Nothing 
   Nothing 
   Nothing 
   hinst
   (wndProc iRf)
 
  _ <- setWinTimer hwnd 0{-tid-} 50{-msec-}
 
  _ <- showWindow hwnd sW_SHOWNORMAL
  updateWindow hwnd
  allocaMessage pump
 
  unregisterClass clsName hinst
 
pump :: LPMSG -> IO ()
pump lpmsg = do
 fContinue <- getMessage lpmsg Nothing
 when fContinue $ do
  _ <- translateMessage lpmsg
  _ <- dispatchMessage lpmsg
  pump lpmsg
 
drawBox4 :: HDC -> [ [Int32] ] -> IO ()
drawBox4 hdc ~[ [x1, y1], [x2, y2], [x3, y3], [x4, y4] ] =
 moveToEx hdc x1 y1 >>
 lineTo   hdc x2 y2 >>
 lineTo   hdc x3 y3 >>
 lineTo   hdc x4 y4 >>
 lineTo   hdc x1 y1
 
drawCube :: HDC -> Matrix -> IO ()
drawCube hdc rot = mapM_ (drawBox4 hdc) $ 
 varMap (splitAt 4) $ 
 map ( 
  (map $ ( + 400).round.( * 100) ) . proj . transform rot)
  cube
 
render :: HWND -> HDC -> Int -> IO ()
render _ hdc = drawCube hdc . rot . fromIntegral
 where
  rot :: Float -> Matrix
  rot x = mxRotXZ $ pi * x/ 180
 
onTimer :: HWND -> IORef Int -> IO ()
onTimer hwnd iRf = do
    invalidateRect (Just hwnd) Nothing True
    modifyIORef' iRf $ \i -> (i + 2) `mod` 360
 
wndProc :: IORef Int -> HWND -> WindowMessage -> WPARAM ->
  LPARAM -> IO LRESULT
wndProc iRf hwnd wm wp lp
  | wm == wM_KEYDOWN    = doFinish
  | wm == wM_LBUTTONDOWN    = doFinish
  | wm == wM_DESTROY    = killTimer (Just hwnd) 0 >> 
               postQuitMessage 0 >> return 0
  | wm == wM_SIZE   = doInvalRender
  | wm == wM_PAINT      = onPaint
  | wm == wM_TIMER  = onTimer hwnd iRf >> return 0
  | otherwise      = defWindowProc (Just hwnd) wm wp lp
  where
    doFinish = sendMessage hwnd wM_CLOSE 1 0 >> return 0
    doInvalRender = do
         invalidateRect (Just hwnd) Nothing True
         return 0
    onPaint     = allocaPAINTSTRUCT $ \ lpps -> do
     hdc <- beginPaint hwnd lpps
     i <- readIORef iRf
     render hwnd hdc i
     endPaint hwnd lpps
     return 0


Добавлено через 5 минут
... ну японцы! В общем, редакторы всякие включая Word этих значков не замечают считая их пробельными. А я уж, не буду третий раз сюда копировать.
1
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
03.06.2015, 20:46
Ответы с готовыми решениями:

Оконное приложение
Здравствуйте, мне необходимо перевести консольную программу в оконное приложение (в окне имеются: 2 StringGrid, 2 Edit(A,B), Button...

Оконное приложение
Доброй ночи!!! Как VS создать оконное приложение какой проект выбрать? Хочу добавить кнопки и место ввода.

Оконное приложение g++
Как на g++ писать оконные приложения?

1
Модератор
 Аватар для Curry
5158 / 3482 / 536
Регистрация: 01.06.2013
Сообщений: 7,550
Записей в блоге: 9
03.06.2015, 20:50  [ТС]
Ладно. Прикреплю исходник к письму. вот.
Вложения
Тип файла: zip Main.zip (1.8 Кб, 8 просмотров)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
03.06.2015, 20:50
Помогаю со студенческими работами здесь

Оконное QT приложение
Как его сделать? Предположим, я выбрал создание пустого проекта. Что написать в main? Я сделал форму в дизайнере. Как прописать её...

Оконное приложение на C++
Товарищи программисты, помогите пожалуйста перейти с делфи на с++. Для начала хочется создать оконную программу с картинкой и кнопкой. При...

Оконное приложение
Добрый день! Помогите, пожалуйста. Вроде много везде написано. Но мне непонятно. Как сделать оконное приложение на Python'е? Можно...

Оконное приложение в g++
Как создать оконное приложение в g++.

Оконное приложение
И снова здравствуйте. Изучаю С++, только в самом начале. Консольные приложения - это круто, но порою надоедает. Насколько сложно делать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Новые блоги и статьи
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
[В процессе разработки] SDL3 для Web (WebAssembly): Сборка библиотек SDL3 и Box2D из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия SDL 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual. . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru