I've been copying the code from this repository 
<https://github.com/zserge/tray> into the nim-lang. I used the winim library. 
And I have a mistake, I haven't been able to fix it for two days! It's a pity 
to throw away such code. Here's the error:
    
    
    D:\nim\test>main.exe
    Traceback (most recent call last)
    D:\nim\test\main.nim(189) main
    D:\nim-1.6.14\lib\system\assign.nim(146) genericShallowAssign
    D:\nim-1.6.14\lib\system\assign.nim(132) genericAssignAux
    D:\nim-1.6.14\lib\system\assign.nim(25) genericAssignAux
    D:\nim-1.6.14\lib\system\assign.nim(22) genericAssignAux
    D:\nim-1.6.14\lib\system\assign.nim(140) genericAssignAux
    SIGSEGV: Illegal storage access. (Attempt to read from nil?)
    
    
    Run

And here's my code:
    
    
    
    
    import winim
    import system
    
    type
      TrayMenu = object
        text: cstring
        disabled: cint
        checked: cint
        cb: proc (menu: ptr TrayMenu)
        context: pointer
        submenu: ptr TrayMenu
    type
      Tray = object
        icon: cstring
        menu: ptr TrayMenu
    
    const
      WM_TRAY_CALLBACK_MESSAGE = WM_USER + 1
      WC_TRAY_CLASS_NAME = "TRAY"
      ID_TRAY_FIRST = 1000
    var
      wc: WNDCLASSEX
      nid: NOTIFYICONDATA
      hwnd: HWND
      hmenu: HMENU = 0
    
    
    
    
    proc memset(dest: pointer, c: cint, count: size_t) {.importc: "memset", 
header: "<string.h>".}
    
    
    
    
    
    proc trayWndProc(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM): 
LRESULT =
      # Ваш код для функции обратного вызова
      case msg:
      of WM_CLOSE:
        DestroyWindow(hwnd)
        return 0
      of WM_DESTROY:
        PostQuitMessage(0)
        return 0
      of WM_TRAY_CALLBACK_MESSAGE:
        if lparam == WM_LBUTTONUP or lparam == WM_RBUTTONUP:
            var p: POINT
            GetCursorPos(p.addr)
            SetForegroundWindow(hwnd)
            let cmd = TrackPopupMenu(hmenu, TPM_LEFTALIGN or TPM_RIGHTBUTTON or
                                            TPM_RETURNCMD or TPM_NONOTIFY,
                                    p.x, p.y, 0, hwnd, nil)
            SendMessage(hwnd, WM_COMMAND, cmd, 0)
            return 0
      of WM_COMMAND:
        if wparam >= ID_TRAY_FIRST:
            var item: MENUITEMINFO
            item.cbSize = UINT(sizeof(MENUITEMINFO))
            item.fMask = UINT(MIIM_ID) or UINT(MIIM_DATA)
            
            if GetMenuItemInfo(hmenu, cast[UINT](wparam), false, item.addr):
                let menu: ptr TrayMenu = cast[ptr TrayMenu](item.dwItemData)
                if (menu != nil) and (not (menu.cb == nil)):
                    menu.cb(menu)
                
                return 0;
      else:
        return 1;
      return DefWindowProc(hwnd, msg, wparam, lparam)
    
    
    
    
    
    proc trayMenu(m: ptr TrayMenu, id: UINT): HMENU =
      var hmenu: HMENU = CreatePopupMenu()
      while m != nil and m.text != nil:
        if m.text == "-":
            InsertMenuW(hmenu, id, MF_SEPARATOR, cast[UINT_PTR](TRUE), "")
        else:
            var item: MENUITEMINFO
            memset(item.addr, 0, sizeof(item))
            item.cbSize = UINT(sizeof(MENUITEMINFO))
            item.fMask = MIIM_ID or MIIM_TYPE or MIIM_STATE or MIIM_DATA
            item.fType = 0
            item.fState = 0
            if m.submenu != nil:
                item.fMask = item.fMask or MIIM_SUBMENU
                item.hSubMenu = trayMenu(m.submenu, id)
            
            if m.disabled:
                item.fState = item.fState or MFS_DISABLED
            
            if m.checked:
                item.fState = item.fState or MFS_CHECKED
            item.wID = id
            item.dwTypeData = cast[LPWSTR](m.text)
            item.dwItemData = cast[ULONG_PTR](m)
            
            InsertMenuItemW(hmenu, id, true, item.addr)
        return hmenu
    
    
    
    
    proc trayUpdate(tray: ptr Tray) =
      var prevmenu: HMENU = hmenu
      var id: UINT = ID_TRAY_FIRST
      hmenu = trayMenu(tray.menu, id)
      SendMessage(hwnd, WM_INITMENUPOPUP, WPARAM(hmenu), 0)
      
      var icon: HICON
      ExtractIconEx(tray.icon, 0, nil, icon.addr, 1)
      
      DestroyIcon(nid.hIcon)
      
      nid.hIcon = icon
      Shell_NotifyIcon(NIM_MODIFY, nid.addr)
      
      if prevmenu != 0:
        DestroyMenu(prevmenu)
    
    
    
    proc trayInit(tray: ptr Tray): int =
      memset(wc.addr, 0, sizeof(wc))
      wc.cbSize = UINT(sizeof(WNDCLASSEX))
      wc.lpfnWndProc = cast[WNDPROC](trayWndProc)
      wc.hInstance = GetModuleHandle(nil)
      wc.lpszClassName = WC_TRAY_CLASS_NAME
      
      if not bool(RegisterClassEx(wc.addr)):
        return -1
      hwnd = CreateWindowEx(0, WC_TRAY_CLASS_NAME, nil, 0, 0, 0, 0, 0, 0, 0, 0, 
cast[LPVOID](0))
      if hwnd == 0:
        return -1
      UpdateWindow(hwnd)
      
      
      memset(nid.addr, 0, sizeof(nid))
      nid.cbSize = UINT(sizeof(NOTIFYICONDATA))
      nid.hWnd = hwnd
      nid.uID = 0
      nid.uFlags = NIF_ICON or NIF_MESSAGE
      nid.uCallbackMessage = WM_TRAY_CALLBACK_MESSAGE
      Shell_NotifyIcon(NIM_ADD, nid.addr)
      
      trayUpdate(tray)
      return 0
    
    
    proc trayLoop(blocking: int): int =
      var msg: MSG
      if blocking != 0:
        GetMessage(addr(msg), cast[HWND](nil), 0, 0)
      else:
        PeekMessage(msg.addr, cast[HWND](nil), 0, 0, PM_REMOVE)
      
      if msg.message == WM_QUIT:
        return -1
      
      TranslateMessage(msg.addr)
      DispatchMessage(msg.addr)
      return 0
    
    proc trayExit() =
      Shell_NotifyIcon(NIM_DELETE, nid.addr)
      
      if nid.hIcon != 0:
        DestroyIcon(nid.hIcon)
      
      if hmenu != 0:
        DestroyMenu(hmenu)
      
      PostQuitMessage(0)
      UnregisterClass(WC_TRAY_CLASS_NAME, GetModuleHandle(nil))
    
    
    
    # Определите функцию обратного вызова для элемента меню
    proc helloCb(menu: ptr TrayMenu) =
      echo "Hello, World!"
    #   trayUpdate(tray.addr)
    
    # Определите структуру и меню системного лотка
    var tray: Tray
    tray.icon = "icon.ico"  # Укажите путь к значку
    tray.menu[] = TrayMenu(text: "hello")
    # Инициализируйте системный лоток
    if trayInit(tray) != 0:
      echo "Ошибка инициализации системного лотка"
      quit(1)
    
    # Запустите цикл обработки событий системного лотка
    while true:
      if trayLoop(1) == -1:
        echo "0"
    
    
    Run

help fix the error please

Reply via email to