win32asm, drawing lines & small is beautiful


http://wp.me/ph3BR-1WJ

 

 

以前抄寫過一個小而美的軟件 https://xiaolaba.wordpress.com/2015/03/06/win32asm-read-write-windows-registry/

這次突然想看看, 怎樣自己做一畫圖的小工具, 事關那些現有的, 不管是 QT / python / labview / C++ / Java / speakthings 都是體積龐大而且運行起來很慢的.

自己只是需要簡單動態地按照 ADC 的讀值 0- 1023 (10BIT), 把它按照時間順序描在座標平面上, 就像是示波器一樣, 根本沒需要精確和臃腫的軟體, 但是沒找著網路上有適合的. 所以翻了幾個網頁, 又看到 FASM 做的小工具, 東抄西湊, 實驗了一下, 終於學會了在 windows 描畫線條, 基本上用 win32 API, GDI32 API, 理論上是 win95 到 win10 都可以免安裝使用的, 而且體積很小, 速度很快. 抄來的源碼, 可以顯示字串, 俺想要畫線, 看了看了, 原來寫字和出線條都是把 “東西" 畫在 client area. 每次收到 WINDOWS 要畫東西的通知就把 “東西" 先放到 “一個籃子裡", 接著系統就幫你拿走 “籃子裡的東西", 顯示畫面, 寫字和畫線一樣, 不過畫線條要用到 GDI32, 修改了一下, 加入畫線條的源碼, 成了. 樣子長這樣, 編譯好的執行檔 paint.exe 就 3K 微型的檔案大小, 厲害.

win32 GDI draw lines

 

加入使用GDI的源碼


gdi32,    'GDI32.DLL'       ; include to draw lines

include 'api\gdi32.inc' ;include to draw lines

 

 

實際畫線條的工作階段, 加在 wmPAINT 裡面, 每次這個軟體啟動或者視窗被移動, win10 就會發通知給這個小程序, 叫他重新畫圖, 所以就看到文字和線條. 看來好像很簡單的邏輯, 實際就是這樣達成的.


;; draw lines
;http://www.informit.com/articles/article.aspx?p=328647&seqNum=3
invoke MoveToEx,[expDc], 0, 0, 0
;                      X,   Y
invoke LineTo,[expDc], 20,  226
invoke LineTo,[expDc], 130, 20
invoke LineTo,[expDc], 240, 100
invoke LineTo,[expDc], 350, 50

 

有興趣學習自己做瑞士軍刀的, 可看看這些教學, https://win32assembly.programminghorizon.com/tut4.html

那些開發系統的人其實很不簡單, 能寫出小而精美的軟體的人更不簡單, 這裡有個 Steve Gibson 老先生, 專門用 asm 寫 WINDOWS 程序的, 有個小小的軟體框架 SIB Small Is Beautiful (https://www.grc.com/freepopular.htm), 可以入門.

 

俺的完整源碼和結果


;http://www.informit.com/articles/article.aspx?p=328647&seqNum=3
;https://board.flatassembler.net/topic.php?p=993
; FASM 1.71.60

format PE GUI 4.0
entry start

include 'win32a.inc'



section '.data' data readable writeable
wHMain         dd   ?
wHInstance     dd   ?

wTitle         db   'FASM - Experiment 01, FASM 1.71.60, 2017-MAR-20 xiaolaba',0
wClsName       db   'EXP01',0

wMsg      MSG
wCls      WNDCLASS

expDc     dd   ?
expTxt    db   'Win32 assembly with FASM is great and easy',0xd,0xa
myTxt     db   'xiaolaba, paint lines, test, 2017-mar-20',0
expPs     PAINTSTRUCT
expRect   RECT


section '.code' code readable executable
start:
; +------------------------------+
; | registering the window class |
; +------------------------------+
invoke    GetModuleHandle,NULL
mov  [wHInstance],eax
mov  [wCls.hInstance],eax
mov  [wCls.lpfnWndProc],window_procedure
mov  [wCls.lpszClassName],wClsName
mov  [wCls.hbrBackground],COLOR_BTNFACE+1
invoke    LoadIcon,0,IDI_APPLICATION
mov  [wCls.hIcon],eax
invoke    LoadCursor,0,IDC_ARROW
mov  [wCls.hCursor],eax
invoke    RegisterClass,wCls

; +--------------------------+
; | creating the main window |
; +--------------------------+
invoke    CreateWindowEx,\
0,\
wClsName,\
wTitle,\
WS_VISIBLE+WS_DLGFRAME+WS_SYSMENU,\
128,\
128,\
512,\
256,\
0,\
0,\
[wHInstance],\
0
mov  [wHMain],eax

; +---------------------------+
; | entering the message loop |
; +---------------------------+
window_message_loop_start:
invoke    GetMessage,wMsg,NULL,0,0
or   eax,eax
je   window_message_loop_end
invoke    TranslateMessage,wMsg
invoke    DispatchMessage,wMsg
jmp  window_message_loop_start

window_message_loop_end:
invoke    ExitProcess,0

; +----------------------+
; | the window procedure |
; +----------------------+
proc window_procedure,hWnd,uMsg,wParam,lParam
push ebx esi edi    ;even the API would preserved, but play safe :p
cmp  [uMsg],WM_DESTROY
je   wmDESTROY
cmp  [uMsg],WM_PAINT
je   wmPAINT

wmDEFAULT:
invoke    DefWindowProc,[hWnd],[uMsg],[wParam],[lParam]
jmp  wmBYE
wmPAINT:
invoke    BeginPaint,[hWnd],expPs
mov  [expDc],eax
invoke    GetClientRect,[hWnd],expRect

;; drawing single line text to window, ignore line change (0x0d, 0x0a)
;; https://msdn.microsoft.com/en-us/library/windows/desktop/dd162498(v=vs.85).aspx
;                    invoke    DrawText,\
;                                   [expDc],\
;                                   expTxt,\
;                                   -1,\
;                                   expRect,\
;                                   DT_CENTER or DT_VCENTER or DT_SINGLELINE

;; drawing multi lines text to window
invoke    DrawText,\
[expDc],\
expTxt,\
-1,\
expRect,\
DT_CENTER or DT_VCENTER

;; draw lines
;http://www.informit.com/articles/article.aspx?p=328647&seqNum=3
invoke MoveToEx,[expDc], 0, 0, 0
;                      X,   Y
invoke LineTo,[expDc], 20,  226
invoke LineTo,[expDc], 130, 20
invoke LineTo,[expDc], 240, 100
invoke LineTo,[expDc], 350, 50

invoke    EndPaint,[hWnd],expPs
jmp  wmBYE

wmDESTROY:
invoke    PostQuitMessage,0
wmBYE:
pop  edi esi ebx
ret
endp



section '.idata' import data readable writable
library   KERNEL32, 'KERNEL32.DLL',\
USER32,   'USER32.DLL',\
gdi32,    'GDI32.DLL'       ; include to draw lines

include 'api\gdi32.inc' ;include to draw lines

import    KERNEL32,\
GetModuleHandle,    'GetModuleHandleA',\
ExitProcess,        'ExitProcess'

import    USER32,\
RegisterClass,      'RegisterClassA',\
CreateWindowEx,     'CreateWindowExA',\
DefWindowProc,      'DefWindowProcA',\
LoadCursor,         'LoadCursorA',\
LoadIcon,           'LoadIconA',\
GetMessage,         'GetMessageA',\
TranslateMessage,   'TranslateMessage',\
DispatchMessage,    'DispatchMessageA',\
BeginPaint,         'BeginPaint',\
GetClientRect,      'GetClientRect',\
DrawText,           'DrawTextA',\
EndPaint,           'EndPaint',\
PostQuitMessage,    'PostQuitMessage'

 

 

 

另外有個C++的源碼解說的, 把SOUND CARD 當作 ADC, 做 FFT 的, 需要修改的話, 要體積龐大的 VISUAL STUDIO 才可以編譯, 也是小而美的作品, Sampling Sound in Windows32, http://www.relisoft.com/freeware/recorder.html

廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s