winform ShowDialog(这个)仍然失败

时间:2015-10-27 04:25:17

标签: c# forms winforms showdialog

我已经知道使用ShowDialog()会导致表单落后于其父窗体。所以我寻找解决方案。

许多人说解决方案是将父表单作为参数传递给子表单。

像这样。

#include <valarray>
#include <vector>
#include <utility>

#include <cmath>
#include <cstddef>
#include <cassert>

template< typename value_type >
struct math
{

    using size_type = std::size_t;

    size_type const dimension_;
    value_type const & eps;

    value_type const zero = value_type(0);
    value_type const one = value_type(1);

private :

    using vector = std::valarray< value_type >;
    using matrix = std::vector< vector >;

    matrix matrix_;
    matrix minor_;

public :

    math(size_type const _dimension,
         value_type const & _eps)
        : dimension_(_dimension)
        , eps(_eps)
        , matrix_(dimension_)
        , minor_(dimension_ - 1)
    { 
        assert(1 < dimension_);
        assert(!(eps < zero));
        for (size_type r = 0; r < dimension_; ++r) {
            matrix_[r].resize(dimension_);
        }
        size_type const minor_size = dimension_ - 1;
        for (size_type r = 0; r < minor_size; ++r) {
            minor_[r].resize(minor_size);
        }
    }

    template< typename rhs = matrix >
    void
    operator = (rhs const & _matrix)
    {
        auto irow = std::begin(matrix_);
        for (auto const & row_ : _matrix) {
            auto icol = std::begin(*irow);
            for (auto const & v : row_) {
                *icol = v;
                ++icol;
            }
            ++irow;
        }
    }

    value_type
    det(matrix & _matrix,
        size_type const _dimension)
    { // calculates lower unit triangular matrix and upper triangular
        assert(0 < _dimension);
        value_type det_ = one;
        for (size_type i = 0; i < _dimension; ++i) {
            vector & ri_ = _matrix[i];
            using std::abs;
            value_type max_ = abs(ri_[i]);
            size_type pivot = i;
            {
                size_type p = i;
                while (++p < _dimension) {
                    value_type y_ = abs(_matrix[p][i]);
                    if (max_ < y_) {
                        max_ = std::move(y_);
                        pivot = p;
                    }
                }
            }
            if (!(eps < max_)) { // regular?
                return zero; // singular
            }
            if (pivot != i) {
                det_ = -det_; // each permutation flips sign of det
                ri_.swap(_matrix[pivot]);
            }
            value_type & dia_ = ri_[i];
            det_ *= dia_; // det is multiple of diagonal elements
            for (size_type j = 1 + i; j < _dimension; ++j) {
                _matrix[j][i] /= dia_;
            }
            for (size_type a = 1 + i; a < _dimension; ++a) {
                vector & a_ = minor_[a - 1];
                value_type const & ai_ = _matrix[a][i];
                for (size_type b = 1 + i; b < _dimension; ++b) {
                    a_[b - 1] = ai_ * ri_[b];
                }
            }
            for (size_type a = 1 + i; a < _dimension; ++a) {
                vector const & a_ = minor_[a - 1];
                vector & ra_ = _matrix[a];
                for (size_type b = 1 + i; b < _dimension; ++b) {
                    ra_[b] -= a_[b - 1];
                }
            }
        }
        return det_;
    }

    value_type
    det(size_type const _dimension)
    {
        return det(matrix_, _dimension);
    }

    value_type
    det()
    {
        return det(dimension_);
    }

};

// main.cpp
#include <iostream>

#include <cstdlib>

int
main()
{
    using value_type = double;
    value_type const eps = std::numeric_limits< value_type >::epsilon();
    std::size_t const dimension_ = 3;
    math< value_type > m(dimension_, eps);
    m = { // example from https://en.wikipedia.org/wiki/Determinant#Laplace.27s_formula_and_the_adjugate_matrix
            {-2.0, 2.0, -3.0},
            {-1.0, 1.0,  3.0},
            { 2.0, 0.0, -1.0}
        };
    std::cout << m.det() << std::endl; // 18
    return EXIT_SUCCESS;
}

但此代码仍然失败。 这就是场景。

  

打开显示对话框的子窗体,然后当子窗体窗口仍处于活动状态时,单击show desktop(或按Window + D),然后打开其他应用程序。   打开应用程序后将其最小化或关闭它。现在关闭或最小化其他应用程序后。

现在,子表单已经在父表单后面了。现在你应该按下alt + tab或者从任务栏中单击它以便再次正常工作。

我会感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

好问题。看起来子对话框是可见的,并且按下了Windows+D,父窗体忽略了请求(或者操作系统可能会阻止向父窗体发送最小化请求,因为它有一个活动的模式对话框)。只是猜测。父表单永远不会发送最小化消息。

您可以使用TOOLS -> Spy++来观察此情况,并注意在显示子对话框并按下Windows+D时缺少发送到父窗口的窗口消息。收到的消息在橙色框中:

enter image description here

这意味着父表单实际上永远不会被最小化。 Windows停止绘制它,但打开另一个窗口会重新打开绘画。

因此,使用WM_ACTIVATEAPP作为参考点,强制最小化父窗体。这具有使子对话框变得不可见的副作用。然后听取SC_RESTORE消息,并重新显示子对话框:

public class RestoreForm : Form {

    private const int SC_RESTORE = 0xF120;
    private const int WM_SYSCOMMAND = 0x0112;
    private const int WM_ACTIVATEAPP = 0x1C;

    public RestoreForm() {
        Button btn1 = new Button { Text = "ShowDialog(...)", AutoSize = true };
        btn1.Click += btn1_Click;

        Controls.Add(btn1);
    }

    protected override void WndProc(ref Message m) {
        base.WndProc(ref m);
        if (f2 != null) {
            if (m.Msg == WM_ACTIVATEAPP) {
                if (f2.WindowState == FormWindowState.Minimized) {
                    this.WindowState = FormWindowState.Minimized;
                }
            }
            else if (m.Msg == WM_SYSCOMMAND) {
                var w = m.WParam.ToInt32();
                if (w == SC_RESTORE) {
                    f2.WindowState = FormWindowState.Normal;
                    //f2.Visible = true; // ignores staying on top of previous parent
                    f2.ShowDialog(this);
                }
            }
        }
    }

    Form f2 = null;
    void btn1_Click(object sender, EventArgs e) {
        f2 = new Form { Text = "Child" };
        f2.ShowDialog(this);
    }
}

答案 1 :(得分:0)

解决此问题的最接近的解决方法是将ShowInTaskbar和MinimizeBox设置为false。

实际上我可以在不禁用最小化框的情况下禁用ShowInTaskbar,但没有意义,允许用户最小化子表单但仍然无法在父表单上执行任何操作。