Регистрация пользовательского win32 класса окна от c#

Это не возможно в Go, так как это скомпилированный и статически типизированный язык. Компилятор должен знать во время компиляции имена и типы переменных (*). То, что вы спрашиваете, это именование переменных во время выполнения, которое не может работать. Тем не менее, крайне маловероятно, что вам это действительно нужно на практике. Карты могут предоставлять аналогичные возможности:

m := make(map[string]string)
m["key"] = "value"

И вы можете создать любой из них во время выполнения. Немного адаптируя ваш пример:

package main

import (
    "fmt"
    "strconv"
    "strings"
    "time"
)

func main() {
    m := make(map[string]string)
    currentMonth := time.Now().Month()
    currentYear := time.Now().Year()
    var month = int(currentMonth)
    var currentDate = strings.Join([]string{strconv.Itoa(currentYear), "-", strconv.Itoa(month)}, "")

    m["key"+currentDate] = "value"
    fmt.Println(m)
}

Распечатывает:

map[key2019-1:value]

(*) За некоторыми исключениями, которые не относятся к данному конкретному обсуждению.

12
задан morechilli 26 September 2008 в 09:34
поделиться

2 ответа

Для записи я наконец заставил это работать. Выпущенный затруднения, которые я испытал, были до строковых проблем маршалинга. Я должен был быть более точным в своем импорте функций win32.

Ниже код, который создаст пользовательский класс окна в c# - полезный для поддержки старых API, которые Вы могли бы иметь, которые полагаются на пользовательские классы окна.

Это должно работать или в WPF или в Winforms, пока насос сообщения работает на потоке.

Править: Обновленный для фиксации катастрофического отказа, о котором сообщают, из-за раннего набора делегата, который переносит обратный вызов. Делегат теперь сохранен как участник и делегат, явно упорядоченный как указатель функции. Это устраняет проблему и помогает понять поведение.

class CustomWindow : IDisposable
{
    delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

    [System.Runtime.InteropServices.StructLayout(
        System.Runtime.InteropServices.LayoutKind.Sequential,
       CharSet = System.Runtime.InteropServices.CharSet.Unicode
    )]
    struct WNDCLASS
    {
        public uint style;
        public IntPtr lpfnWndProc;
        public int cbClsExtra;
        public int cbWndExtra;
        public IntPtr hInstance;
        public IntPtr hIcon;
        public IntPtr hCursor;
        public IntPtr hbrBackground;
        [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
        public string lpszMenuName;
        [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
        public string lpszClassName;
    }

    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    static extern System.UInt16 RegisterClassW(
        [System.Runtime.InteropServices.In] ref WNDCLASS lpWndClass
    );

    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr CreateWindowExW(
       UInt32 dwExStyle,
       [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
       string lpClassName,
       [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
       string lpWindowName,
       UInt32 dwStyle,
       Int32 x,
       Int32 y,
       Int32 nWidth,
       Int32 nHeight,
       IntPtr hWndParent,
       IntPtr hMenu,
       IntPtr hInstance,
       IntPtr lpParam
    );

    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    static extern System.IntPtr DefWindowProcW(
        IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam
    );

    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    static extern bool DestroyWindow(
        IntPtr hWnd
    );

    private const int ERROR_CLASS_ALREADY_EXISTS = 1410;

    private bool m_disposed;
    private IntPtr m_hwnd;

    public void Dispose() 
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing) 
    {
        if (!m_disposed) {
            if (disposing) {
                // Dispose managed resources
            }

            // Dispose unmanaged resources
            if (m_hwnd != IntPtr.Zero) {
                DestroyWindow(m_hwnd);
                m_hwnd = IntPtr.Zero;
            }

        }
    }

    public CustomWindow(string class_name){

        if (class_name == null) throw new System.Exception("class_name is null");
        if (class_name == String.Empty) throw new System.Exception("class_name is empty");

        m_wnd_proc_delegate = CustomWndProc;

        // Create WNDCLASS
        WNDCLASS wind_class = new WNDCLASS();
        wind_class.lpszClassName = class_name;
        wind_class.lpfnWndProc = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(m_wnd_proc_delegate);

        UInt16 class_atom = RegisterClassW(ref wind_class);

        int last_error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();

        if (class_atom == 0 && last_error != ERROR_CLASS_ALREADY_EXISTS) {
            throw new System.Exception("Could not register window class");
        }

        // Create window
        m_hwnd = CreateWindowExW(
            0,
            class_name,
            String.Empty,
            0,
            0,
            0,
            0,
            0,
            IntPtr.Zero,
            IntPtr.Zero,
            IntPtr.Zero,
            IntPtr.Zero
        );
    }

    private static IntPtr CustomWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) 
    {
        return DefWindowProcW(hWnd, msg, wParam, lParam);
    }

    private WndProc m_wnd_proc_delegate;
}
34
ответ дан 2 December 2019 в 04:26
поделиться

1) Можно просто разделить нормальный класс Windows Forms на подклассы... никакая потребность во всех тех вызовах win32, просто необходимо проанализировать сообщение WndProc, вручную... все.

2) Можно импортировать Систему. Windows. Пространство имен форм и использование это вместе с WPF, я полагаю, что не будет никаких проблем, пока Вы не переплетаете слишком много формы окон в свое приложение WPF. Вы просто хотите инстанцировать своей пользовательской скрытой формы к receieve, сообщение является тем правом?

пример разделения на подклассы WndProc:

protected override void WndProc(ref System.Windows.Forms.Message m)
{
   // *always* let the base class process the message
   base.WndProc(ref m);

   const int WM_NCHITTEST = 0x84;
   const int HTCAPTION = 2;
   const int HTCLIENT = 1;

   // if Windows is querying where the mouse is and the base form class said
   // it's on the client area, let's cheat and say it's on the title bar instead
   if ( m.Msg == WM_NCHITTEST && m.Result.ToInt32() == HTCLIENT )
      m.Result = new IntPtr(HTCAPTION);
}

Так как Вы уже знаете RegisterClass и все те вызовы Win32, я предполагаю, что сообщение WndProc не было бы проблемой для Вас...

0
ответ дан 2 December 2019 в 04:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: