C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: Windows Mobile の RegisterClass


(過去ログ 78 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■45897 / inTopicNo.1)  Windows Mobile の RegisterClass
  
□投稿者/ こう (1回)-(2010/01/21(Thu) 17:42:25)

分類:[C#] 

訳あって以下の環境で非表示ウィンドウの作成を行おうと考えております。

OS:Windows Mobile 6.1
言語:C#(コンソールアプリケーション)

ところが、RegisterClassW 関数を実行すると「NotSupportedException」の
例外が発生します。

delegate を使用し、WndProc関数のアドレス指定に問題があると思われますが、
解決方法が見つからず困っております。
情報をお願いします。

以下、長くなりますが、ソースになります。
----------------------------------------------------------------------

    class Program
    {
        private delegate int WndProcDelegate(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
        private static WndProcDelegate wProc = null;

        private const int WHITE_BRUSH = 0;
        private static string appName = "testApp";

        public enum ClassStyles : uint
        {
            CS_VREDRAW = 0x0001,
            CS_HREDRAW = 0x0002,
            CS_DBLCLKS = 0x0008,
            CS_OWNDC = 0x0020,
            CS_CLASSDC = 0x0040,
            CS_PARENTDC = 0x0080,
            CS_NOCLOSE = 0x0200,
            CS_SAVEBITS = 0x0800,
            CS_BYTEALIGNCLIENT = 0x1000,
            CS_BYTEALIGNWINDOW = 0x2000,
            CS_GLOBALCLASS = 0x4000,
            CS_IME = 0x00010000,
            CS_DROPSHADOW = 0x00020000
        }

        [StructLayout(LayoutKind.Sequential)]
        struct WNDCLASS
        {
            public uint style;
            [MarshalAs(UnmanagedType.FunctionPtr)]
            public WndProcDelegate lpfnWndProc;
            public int cbClsExtra;
            public int cbWndExtra;
            public IntPtr hInstance;
            public IntPtr hIcon;
            public IntPtr hCursor;
            public IntPtr hbrBackground;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string lpszMenuName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string lpszClassName;
        }

        [DllImport("coredll.dll")]
        private static extern IntPtr GetStockObject(int fnObject);

        [DllImport("coredll.dll", SetLastError = true)]
        private static extern ushort RegisterClassW(ref WNDCLASS lpWndClass);

        static void Main(string[] args)
        {
            WNDCLASS wc = new WNDCLASS();
            wProc = new WndProcDelegate(WndProc);

            try
            {
                wc.style = (uint)(ClassStyles.CS_HREDRAW | ClassStyles.CS_VREDRAW);
                wc.lpfnWndProc = wProc;
                wc.cbClsExtra = 0;
                wc.cbWndExtra = 0;
                wc.hInstance = IntPtr.Zero;
                wc.hIcon = IntPtr.Zero;
                wc.hCursor = IntPtr.Zero;
                wc.hbrBackground = GetStockObject(WHITE_BRUSH);
                wc.lpszMenuName = string.Empty;
                wc.lpszClassName = appName;

                if (RegisterClassW(ref wc) != 0)
                {
                    // CreateWindowExW コール

                    // Message ループ
                }
            }
            catch (Exception ex)
            {
                int err = Marshal.GetLastWin32Error();
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }

        }

        private static int WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
        {
            return 0;
        }
    }

----------------------------------------------------------------------

引用返信 編集キー/
■45941 / inTopicNo.2)  Re[1]: Windows Mobile の RegisterClass
□投稿者/ やじゅ (1471回)-(2010/01/22(Fri) 07:20:21)
やじゅ さんの Web サイト
No45897 (こう さん) に返信
> ところが、RegisterClassW 関数を実行すると「NotSupportedException」の
> 例外が発生します。
> wc.hIcon = IntPtr.Zero;
> wc.hCursor = IntPtr.Zero;
> wc.hbrBackground = GetStockObject(WHITE_BRUSH);

下記の記述どおりだと、あやしいのはBackgroundだけどね。
hIcon、hCursor、hbrBackgroundはWindows MobileではサポートされていませんのでNULLをセットします。
http://emboss.blog28.fc2.com/blog-entry-84.html
引用返信 編集キー/
■45975 / inTopicNo.3)  Re[2]: Windows Mobile の RegisterClass
□投稿者/ こう (3回)-(2010/01/22(Fri) 15:35:20)
No45941 (やじゅ さん) に返信

情報ありがとうございます。
RegisterClassW 問題が解決しました。

原因は、WndProc関数のアドレス指定方法でした。
以下の部分を修正しました。

        [StructLayout(LayoutKind.Sequential)]
        struct WNDCLASS
        {
            public uint style;
            [MarshalAs(UnmanagedType.FunctionPtr)]
            public WndProcDelegate lpfnWndProc;    -----> public IntPtr lpfnWndProc;
                :
        }


        wc.lpfnWndProc = wProc;   ------> wc.lpfnWndProc = Marshal.GetFunctionPointerForDelegate(wProc);


しかし、新たな問題が発生しています。
メッセージキューからメッセージを取り出す GetMessageW が必ず 0(WM_QUIT)で返ってくるのです。
ウィンドウスタイル指定が原因かも知れません。(組み合わせ色々試していますが原因不明です。)

以下ソースになります。
--------------------------------------------------------------------
        [DllImport("coredll.dll", SetLastError = true)]
        private static extern IntPtr CreateWindowExW(
            WindowExStyles dwExStyle,
            [MarshalAs(UnmanagedType.LPWStr)]
            string lpClassName,
            [MarshalAs(UnmanagedType.LPWStr)]
            string lpWindowName,
            WindowStyles dwStyle,
            uint x,
            uint y,
            uint nWidth,
            uint nHeight,
            IntPtr hWndParent,
            IntPtr hMenu,
            IntPtr hInstance,
            IntPtr lpParam);

        [StructLayout(LayoutKind.Sequential)]
        public struct MSG
        {
            public IntPtr hwnd;
            public uint message;
            public IntPtr wParam;
            public IntPtr lParam;
            public uint time;
            public Point pt;
        }

        [DllImport("coredll.dll")]
        private static extern int GetMessageW(MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);

        [DllImport("coredll.dll")]
        private static extern int TranslateMessage(ref MSG lpMsg);

        [DllImport("coredll.dll")]
        static extern IntPtr DispatchMessage(ref MSG lpmsg);

     :
     :

                if (RegisterClassW(ref wc) != 0)
                {
                    // CreateWindowExW コール
                    IntPtr hWnd = CreateWindowExW(0, className, string.Empty, 0,
                                                    0, 0, 100, 200,
                                                    IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);

                    if (hWnd != IntPtr.Zero)
                    {
                        // Message ループ
                        MSG msg = new MSG();
                        int ret;
                        while ((ret = GetMessageW(msg, IntPtr.Zero, 0, 0)) != 0)
                        {
                            if (ret == -1)
                            {
                                break;
                            }
                            else
                            {
                                TranslateMessage(ref msg);
                                DispatchMessage(ref msg);
                            }
                        }
                    }
                }
--------------------------------------------------------------------


引用返信 編集キー/
■45983 / inTopicNo.4)  Re[3]: Windows Mobile の RegisterClass
□投稿者/ Hongliang (549回)-(2010/01/22(Fri) 16:39:15)
GetMessage の第一引数は LPMSG ですから ref/out が必要ですよ。
それから wProc は static メンバにするか、あるいはメッセージループ完了後に GC.KeepAlive しとかないとまずいことになると思います。
引用返信 編集キー/
■45984 / inTopicNo.5)  Re[4]: Windows Mobile の RegisterClass
□投稿者/ こう (4回)-(2010/01/22(Fri) 16:54:46)
No45983 (Hongliang さん) に返信
> GetMessage の第一引数は LPMSG ですから ref/out が必要ですよ。
> それから wProc は static メンバにするか、あるいはメッセージループ完了後に GC.KeepAlive しとかないとまずいことになると思います。

確かに、GetMessage の第一引数に ref 抜けてました。
ありがとうございました。

[DllImport("coredll.dll")]
private static extern int GetMessageW(ref MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -