分享
  1. 首页
  2. 文章

用golang在windows下创建窗口并显示图片

独立风华 · · 10031 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

这是我编写的一个包(库):

github.com/jthmath/winapi

这个包实现了一些Windows API函数的golang封装。


至于说为什么不用现成的(如walk),我会另文解释。我们还是先看一看代码吧。


第1步,注册窗口类

func MyRegisterClass(hInstance winapi.HINSTANCE) (atom uint16, err error) {
  var wc winapi.WNDCLASS
  wc.Style = winapi.CS_HREDRAW | winapi.CS_VREDRAW
  wc.PfnWndProc = WndProc
  wc.CbClsExtra = 0
  wc.CbWndExtra = 0
  wc.HInstance = hInstance
  wc.HIcon = 0
  wc.HCursor, err = winapi.LoadCursorById(0, winapi.IDC_ARROW)
  if err != nil {
    return
  }
  wc.HbrBackground = winapi.COLOR_WINDOW + 1
  wc.PszMenuName = ""
  wc.PszClassName = "主窗口类"
  wc.HIconSmall = 0
  return winapi.RegisterClass(&wc)
}

第2步,创建窗口

wnd, err := winapi.CreateWindow("主窗口类", "golang windows 编程",
  winapi.WS_OVERLAPPEDWINDOW, 0,
  winapi.CW_USEDEFAULT, winapi.CW_USEDEFAULT, winapi.CW_USEDEFAULT, winapi.CW_USEDEFAULT,
  0, 0, Inst, 0)
if err != nil {
  fmt.Println("创建窗口失败")
  return 0
}
fmt.Println("创建窗口成功", wnd)
winapi.ShowWindow(wnd, winapi.SW_SHOW)
winapi.UpdateWindow(wnd)

第3步,主消息循环

var msg winapi.MSG
msg.Message = winapi.WM_QUIT + 1 // 让它不等于 winapi.WM_QUIT
for winapi.GetMessage(&msg, 0, 0, 0) > 0 {
  winapi.TranslateMessage(&msg)
  winapi.DispatchMessage(&msg)
}

这些步骤,与用C或C++编写Windows程序没什么两样,只不过,现在的函数是golang风格。


当然,还要在相应WM_PAINT消息的时候贴图。

func WndProc(hWnd winapi.HWND, message uint32, wParam uintptr, lParam uintptr) uintptr {
  var hTemp winapi.HANDLE
  switch message {
  case winapi.WM_CREATE:
    hTemp, _ = winapi.LoadImageByName(0, "D:\0004円.bmp",
      winapi.IMAGE_BITMAP, 0, 0, winapi.LR_LOADFROMFILE)
    hBitmap = winapi.HBITMAP(hTemp)
  case winapi.WM_PAINT:
    OnPaint(hWnd)
  case winapi.WM_DESTROY:
    winapi.PostQuitMessage(0)
  case winapi.WM_COMMAND:
    OnCommand(hWnd, wParam, lParam)
  default:
    return winapi.DefWindowProc(hWnd, message, wParam, lParam)
  }
  return 0
}
func OnPaint(hWnd winapi.HWND) {
  var err error
  var ps winapi.PaintStruct
  hdc, err := winapi.BeginPaint(hWnd, &ps)
  if err != nil {
    return
  }
  defer winapi.EndPaint(hWnd, &ps) // defer 终于有用武之地了
  // HDC mdc = CreateCompatibleDC(hdc);
  mdc, err := winapi.CreateCompatibleDC(hdc)
  if err != nil {
    return
  }
  defer winapi.DeleteDC(mdc)
  winapi.SelectObject(mdc, winapi.HGDIOBJ(hBitmap))
  winapi.BitBlt(hdc, 0, 0, 480, 640, mdc, 0, 0, winapi.SRCCOPY)
}

效果如下:


完整代码

package main
import (
  "fmt"
  "runtime"
  "github.com/jthmath/winapi"
)
// 全局变量
var hBitmap winapi.HBITMAP
func init() {
  runtime.GOMAXPROCS(runtime.NumCPU())
}
func main() {
  inst, err := winapi.GetModuleHandle("")
  if err != nil {
    fmt.Println("获取实例失败")
    return
  }
  r := WinMain(inst, "", 0)
  fmt.Println("WinMain函数返回", r)
}
func WinMain(Inst winapi.HINSTANCE, Cmd string, nCmdShow int32) int32 {
  var err error
  // 1. 注册窗口类
  atom, err := MyRegisterClass(Inst)
  if err != nil {
    fmt.Println("注册窗口类失败")
    return 0
  }
  fmt.Println("注册窗口类成功", atom)
  // 2. 创建窗口
  wnd, err := winapi.CreateWindow("主窗口类", "golang windows 编程",
    winapi.WS_OVERLAPPEDWINDOW, 0,
    winapi.CW_USEDEFAULT, winapi.CW_USEDEFAULT, winapi.CW_USEDEFAULT, winapi.CW_USEDEFAULT,
    0, 0, Inst, 0)
  if err != nil {
    fmt.Println("创建窗口失败")
    return 0
  }
  fmt.Println("创建窗口成功", wnd)
  winapi.ShowWindow(wnd, winapi.SW_SHOW)
  winapi.UpdateWindow(wnd)
  // 3. 主消息循环
  var msg winapi.MSG
  msg.Message = winapi.WM_QUIT + 1 // 让它不等于 winapi.WM_QUIT
  for winapi.GetMessage(&msg, 0, 0, 0) > 0 {
    winapi.TranslateMessage(&msg)
    winapi.DispatchMessage(&msg)
  }
  return int32(msg.WParam)
}
func WndProc(hWnd winapi.HWND, message uint32, wParam uintptr, lParam uintptr) uintptr {
  var hTemp winapi.HANDLE
  switch message {
  case winapi.WM_CREATE:
    hTemp, _ = winapi.LoadImageByName(0, "D:\0004円.bmp",
      winapi.IMAGE_BITMAP, 0, 0, winapi.LR_LOADFROMFILE)
    hBitmap = winapi.HBITMAP(hTemp)
  case winapi.WM_PAINT:
    OnPaint(hWnd)
  case winapi.WM_DESTROY:
    winapi.PostQuitMessage(0)
  case winapi.WM_COMMAND:
    OnCommand(hWnd, wParam, lParam)
  default:
    return winapi.DefWindowProc(hWnd, message, wParam, lParam)
  }
  return 0
}
func OnPaint(hWnd winapi.HWND) {
  var err error
  var ps winapi.PaintStruct
  hdc, err := winapi.BeginPaint(hWnd, &ps)
  if err != nil {
    return
  }
  defer winapi.EndPaint(hWnd, &ps) // defer 终于有用武之地了
  // HDC mdc = CreateCompatibleDC(hdc);
  mdc, err := winapi.CreateCompatibleDC(hdc)
  if err != nil {
    return
  }
  defer winapi.DeleteDC(mdc)
  winapi.SelectObject(mdc, winapi.HGDIOBJ(hBitmap))
  // 这个函数的第4、5个参数分别是图片的宽、高
  // 为了简便起见,我直接写在了这里
  // 实际项目中当然要用过程序获取一下
  winapi.BitBlt(hdc, 0, 0, 480, 640, mdc, 0, 0, winapi.SRCCOPY)
}
func OnCommand(hWnd winapi.HWND, wParam uintptr, lParam uintptr) {
  // 暂时不需要特殊处理 WM_COMMAND
  winapi.DefWindowProc(hWnd, winapi.WM_COMMAND, wParam, lParam)
}
func MyRegisterClass(hInstance winapi.HINSTANCE) (atom uint16, err error) {
  var wc winapi.WNDCLASS
  wc.Style = winapi.CS_HREDRAW | winapi.CS_VREDRAW
  wc.PfnWndProc = WndProc
  wc.CbClsExtra = 0
  wc.CbWndExtra = 0
  wc.HInstance = hInstance
  wc.HIcon = 0
  wc.HCursor, err = winapi.LoadCursorById(0, winapi.IDC_ARROW)
  if err != nil {
    return
  }
  wc.HbrBackground = winapi.COLOR_WINDOW + 1
  wc.PszMenuName = ""
  wc.PszClassName = "主窗口类"
  wc.HIconSmall = 0
  return winapi.RegisterClass(&wc)
}

有疑问加站长微信联系(非本文作者)

本文来自:开源中国博客

感谢作者:独立风华

查看原文:用golang在windows下创建窗口并显示图片

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
10031 次点击 ∙ 3 赞
5 回复 | 直到 2022年03月19日 15:51:02
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏