我已经知道使用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或者从任务栏中单击它以便再次正常工作。
我会感谢您的帮助。
答案 0 :(得分:1)
好问题。看起来子对话框是可见的,并且按下了Windows+D
,父窗体忽略了请求(或者操作系统可能会阻止向父窗体发送最小化请求,因为它有一个活动的模式对话框)。只是猜测。父表单永远不会发送最小化消息。
您可以使用TOOLS -> Spy++
来观察此情况,并注意在显示子对话框并按下Windows+D
时缺少发送到父窗口的窗口消息。收到的消息在橙色框中:
这意味着父表单实际上永远不会被最小化。 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,但没有意义,允许用户最小化子表单但仍然无法在父表单上执行任何操作。