1

私はコンパクトなフレームワーク フォーム アプリケーションを持っています。これは、特にフル ウィンドウ サイズではないポップアップ ウィンドウを表示します。

現状では、これらのポップアップの 1 つが表示されているときに、タイトル バーを使用して、表示されている画面領域の外にドラッグすることができます。これにより、ポップアップが入力を待っているが表示されないため、フォームが応答していないという印象が与えられます。

したがって、フォームの移動を検出して、位置をリセットして画面の中央に保つことができるようにしたいと考えています。しかし、私はこれを達成することができないようです。

これまでのところ、フォームをサブクラス化し、WM_MOVE、WM_SIZE、または WM_WINDOWPOSCHANGED メッセージを探してみましたが、これらのメッセージが WndProc に表示されることはありません (すべてのメッセージをログに記録しようとしましたが、フォームが表示されるとメッセージを受信しませんが、移動中または移動後に、実際に一度表示された WndProc の次のメッセージは、フォーム上でボタンがクリックされたときです)。

また、OnPaint/OnPaintBackground イベント中にフォームの現在の場所を検出しようとしました。これは、フォームに MainMenu コントロールが含まれていない限り機能します。MainMenu コントロールが存在する場合、メニューがある画面の下部までフォームをドラッグすると、OnPaint/OnPaintBackground イベントは発生しなくなります (表示されなくなるため、再描画する必要はありません)。

アイデアが不足しています。助言がありますか?

4

2 に答える 2

4

Moveable WinForm ソリューションを更新しました: http://www.hjgode.de/wp/2012/11/07/mobile-development-move-your-form/

ここに画像の説明を入力

更新されたソース コードはhttp://code.google.com/p/win-mobile-code/source/browse/#svn%2Ftrunk%2FMoveableWinForm%2FMovableFormにあります。

msg send to form を取得するための重要なサブクラス化コードは次のとおりです (winapi.cs を参照)。

    #region subclassing
    public class subclassForm:IDisposable
    {
        #region delegate_event_stuff
        public class wndprocEventArgs : EventArgs
        {
            public IntPtr hWnd;
            public uint msg;
            public IntPtr lParam;
            public IntPtr wParam;
            public wndprocEventArgs(IntPtr lphWnd, uint iMsg, IntPtr lpLParam, IntPtr lpWParam)
            {
                hWnd = lphWnd;
                msg = iMsg;
                lParam = lpLParam;
                wParam = lpWParam;
            }
        }

        public delegate void wndProcEventHandler(object sender, wndprocEventArgs wndProcArgs);
        public event wndProcEventHandler wndProcEvent;
        void onWndProcEvent(wndprocEventArgs wa)
        {
            if (this.wndProcEvent == null)
                return;
            wndProcEvent(this, wa);
        }
        #endregion

        public enum WNDMSGS:uint{
            WM_MOVE=0x0003,
            WM_SIZE=0x0005,
        }
        public subclassForm(System.Windows.Forms.Form form)
        {
            _form = form;
            lpPrevWndFunc = _subClassForm(_form);
        }
        public void Dispose()
        {
            unsubClassForm(_form);
        }
        IntPtr lpPrevWndFunc=IntPtr.Zero;
        System.Windows.Forms.Form _form;

        static WndProcDelegate persistentWndProc;
        IntPtr _subClassForm(System.Windows.Forms.Form form)
        {
            //avoid multiple subclassing
            if (lpPrevWndFunc != IntPtr.Zero)
                return IntPtr.Zero;
            persistentWndProc = WndProc;
            lpPrevWndFunc = (IntPtr)GetWindowLong(form.Handle, GWL_WNDPROC);
            SetWindowLong(form.Handle, GWL_WNDPROC, persistentWndProc);
            return lpPrevWndFunc;
        }
        IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
        {
            System.Diagnostics.Debug.WriteLine("HWND: " + hWnd + " MSG: " + msg + " WPARAM: " + wParam + " LPARAM: " + lParam);
            onWndProcEvent(new wndprocEventArgs(hWnd, msg, lParam, wParam));
            return CallWindowProc(lpPrevWndFunc, hWnd, msg, wParam, lParam);
        }
        bool unsubClassForm(System.Windows.Forms.Form form)
        {
            bool bRet = false;
            if (lpPrevWndFunc == IntPtr.Zero)
                return bRet;
            if (SetWindowLong(form.Handle, GWL_WNDPROC, lpPrevWndFunc.ToInt32()) != 0)
            {
                bRet = true;
                lpPrevWndFunc = IntPtr.Zero;
            }
            return bRet;
        }
    }
    #endregion

コードを使用すると、フォームが移動され、おそらくプライマリ画面の境界の外に移動した場合に「認識」できるはずです。

于 2013-01-18T11:31:06.133 に答える
0

これはばかげた解決策ですが、フォームにタイマーを配置することを検討しましたか?

public partial class Form1 : Form
{
    private Timer CheckLocation { get; set; }
    private Point FirstLocation { get; set; }

    public Form1()
    {
        InitializeComponent();

        FirstLocation = Location;
        CheckLocation.Tick += new EventHandler(CheckLocation_Tick);
    }

    void CheckLocation_Tick(object sender, EventArgs e)
    {
        if (FirstLocation != Location)
        {
            Location = FirstLocation;
        }
    }
}
于 2013-01-24T13:53:52.653 に答える