用nim寫一個簡單的windows程序

編譯:nim c --app:gui hello.nim    後者有控制檯的: nim c hello.nim

關於使用vs 作爲nim生成C代碼的編譯器,上篇博客中說過。

nim 和 C太像了,感覺就像C的語法糖。

下面看代碼:

import
    windows
#{.link:"hello.res".}
const
    IDI_TEST_GUI = 107
    IDC_TEST_GUI = 109
proc MakeIntResource(id:int):LPCSTR = 
    cast[LPSTR](id)
type
    MyWnd = object
        hWnd*:HWND
method `hWnd=`*(this:var MyWnd,value:HWND) =
    this.hWnd = value
method hWnd*(this:var MyWnd) :HWND = this.hWnd
var g_wnd : MyWnd = MyWnd()
var tls_index : DWORD = 0
let instance = GetModuleHandle(nil)
var 
    hbmp : HBITMAP
    Bkbmp: BITMAP
proc Init(): bool =
    hbmp = LoadImage(instance,r"1.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE)
    if hbmp !=0 :
        let ret = GetObject(cast[HGDIOBJ](hbmp),cast[int32](sizeof(BITMAP)),cast[LPVOID](addr Bkbmp))
        if ret!=1 :
            return true
    else:
        echo "LoadImage failed"
        return false
proc OnPaint(hwnd:HWND) :LRESULT {.stdcall.} =
    var ps:PAINTSTRUCT
    let hdc = BeginPaint(hwnd,ps)
    var rt : RECT
    discard GetClientRect(hwnd,rt)
    let hb = CreateSolidBrush(0x00ff00ff)
    discard FillRect(hdc,rt,hb)
    discard Rectangle(hdc,10,10,100,100)
    discard DeleteObject(hb)
    let memdc = CreateCompatibleDC(hdc)
    let hbmp = LoadImage(instance,r"1.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE)
    let old = SelectObject(memdc,hbmp)
    discard Bitblt(hdc,0,0,rt.BottomRight.x,rt.BottomRight.y,memdc,0,0,SRCCOPY)
    discard SelectObject(memdc,old)
    discard DeleteObject(hbmp)
    discard DeleteDC(memdc)
    discard EndPaint(hwnd,ps)
proc mywndproc(hwnd:HWND,msg:WINUINT,wParam:WPARAM,lParam:LPARAM) : LRESULT {.stdcall.} = 
    case msg:
    of WM_CREATE:
        var 
            hmenu:HMENU
            info :MENUITEMINFO
            hsubmenu:HMENU
        let hicon = LoadImage(0,"nim.ico",IMAGE_ICON,0,0,LR_LOADFROMFILE)
        discard SetClassLong(hwnd,GCL_HICON,cast[LONG](hicon))
        hmenu = CreateMenu()
        info.cbSize = 44
        info.fMask = MIIM_STRING or MIIM_ID 
        info.fType = MFT_STRING
        info.wID = 100
        info.cch = 4
        info.dwTypeData = "test"
        info.hbmpItem = 0
        if InsertMenuItem(hmenu,0,0,addr(info)) !=1 :
            echo "InsertMenu failed=",GetLastError()
        info.wID=101
        info.cch=4
        info.dwTypeData = "Help"
        #discard InsertMenuItem(hmenu,1,0,addr(info))
        info.wID = 102
        info.fMask = MIIM_SUBMENU or MIIM_STRING
        hsubmenu = CreatePopupMenu()
        info.hSubMenu = hsubmenu
        if InsertMenu(hsubmenu,0,MF_BYCOMMAND,100,"test")!=1 :
            echo "InsertMenu err=",GetLastError()
        discard InsertMenu(hsubmenu,0,MF_BYCOMMAND,100,"exit")
        discard InsertMenu(hsubmenu,0,MF_BYCOMMAND,100,"about")
        discard InsertMenuItem(hmenu,2,0,addr(info))
        #discard InsertMenu(hmenu,0,MF_BYCOMMAND,100,"test")
        #discard InsertMenu(hmenu,0,MF_BYCOMMAND,101,"file")
        discard SetMenu(hwnd,hmenu)
        var mywnd = cast[ptr MyWnd](TlsGetValue(tls_index))
        mywnd.hWnd = hwnd
        echo "WM_CREATE enter",hwnd
        return 1
    of WM_PAINT:
        discard OnPaint(hwnd)
        return 1
    of WM_CLOSE:
        #discard MessageBox(0,"close","msg",0)
        discard DestroyWindow(hwnd)        
    of WM_DESTROY:
        #discard MessageBox(0,"DestroyWindow:","msg",0)
        PostQuitMessage(WM_QUIT)
    else:discard
    return DefWindowProc(hwnd,msg,wParam,lParam)
proc MyRegisterWindow():ATOM =
    var wnd_cls : WNDCLASSEX
    wnd_cls.cbSize =cast[WINUINT](sizeof(WNDCLASSEX))
    wnd_cls.cbClsExtra = 0
    wnd_cls.cbWndExtra = 0
    wnd_cls.hInstance = instance
    wnd_cls.hIcon = LoadIcon(instance,IDI_HAND)
    wnd_cls.hCursor = LoadCursor(0,IDC_ARROW)
    wnd_cls.hbrBackground = COLOR_WINDOW+1
    wnd_cls.lpszMenuName = nil
    wnd_cls.lpszClassName = r"haha"
    wnd_cls.lpfnWndProc = mywndproc
    wnd_cls.style = CS_HREDRAW or CS_VREDRAW
    RegisterClassEx(wnd_cls)
proc InitWindow() : HWND =
    var style:DWORD = 0
    var cls_name = r"haha"
    var caption : cstring = r"hello"
    var
        x,y,width,height:DWORD
    x = 0
    y = 0
    width = Bkbmp.bmWidth
    height = Bkbmp.bmHeight
    var parent:HWND = 0
    var menu:HMENU =0
    var creat_param : LPVOID = nil
    tls_index = TlsAlloc()
    if tls_index==0xffffffff:quit(1)
    discard TlsSetValue(tls_index,addr(g_wnd))
    let hwnd = CreateWindowEx(style,cls_name,caption,
        WS_OVERLAPPEDWINDOW,x,y,width,height,parent,menu,instance,creat_param)
    if hwnd == 0:
        let err = GetLastError()
        discard MessageBox(0,"createwindowex error:" & $err,"msg",0)
        #echo "createwindowex error:",GetLastError()
    else:
        g_wnd.hWnd = hwnd

        discard ShowWindow(hwnd,SW_SHOW)
        discard UpdateWindow(hwnd)
    result = hwnd

proc main() =
    if not Init():
        quit(0)
    let ret = MyRegisterWindow()
    if ret != 0 :
        if InitWindow() == 0 :
            quit(0)
        var msg : MSG        
        while GetMessageW(msg,0,0,0)!=0:
            discard TranslateMessage(msg)
            discard DispatchMessage(msg)
    else:
        echo "RegisterClass failed"
main()

自己隨便找了張圖片,生成如下:


使用windows API 的時候如果哪個API 在windows.nim 中沒有,那麼自己參考windows.nim 聲明一下就可以了。還有enum , 常量,結構體都有對應的元素。

 

 

發佈了80 篇原創文章 · 獲贊 22 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章