-1

私は、フォームを必要とする最初の C++ プロジェクトに取り組んでいますが、頭を悩ませているようです。主に私の問題は、フォームをマルチスレッド化していないことに関係していると思いますが、適切な実装がわかりません。誰かが私が行った場所を正確に指摘して、マペットのように見せてくれることを望んでいました. (心のフェイントに警告します。グローバル変数を使用して概念実証をすばやく作成しました。すべてが多かれ少なかれ正しく機能するようになったら、戻ってすべてを適切に保護します)

*編集:明確にするために、問題はメインスレッドですべてを実行することのようです。フォーム全体に対して単一の新しいスレッドを作成することは可能ですか、それとも個々のコントロールごとに新しいスレッドを作成する必要がありますか?フォーム?

Winmain.cpp

フォームを初期化し、フォーム上の情報を更新する/フォームを更新するメイン関数。

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    using namespace Interface;
    cooldowns ^ CDwin = gcnew cooldowns;
    CDwin->Show();
    CDwin->Location = Point(0,0);

    while (true)
    {
        CDwin->timer1->Text = timer1Duration.ToString();
        CDwin->timer1Progress->Value = timer1Value;
        CDwin->timer1->Refresh();
        CDwin->timer1Progress->Refresh();

        //collect info to populate CDwin values for next cycle
        //something tells me this sleep could be part of the problem?

        Sleep(50);
    }
}

フォーム.h

#pragma once

namespace Interface {

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using namespace System::Threading;

    /// <summary>
    /// Summary for cooldowns
    /// </summary>
    public ref class cooldowns : public System::Windows::Forms::Form
    {
    public:
        cooldowns(void)
        {
            InitializeComponent();
            //
            //TODO: Add the constructor code here
            //
        }

    protected:
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        ~cooldowns()
        {
            if (components)
            {
                delete components;
            }
        }
    public: System::Windows::Forms::ProgressBar^  timer1Progress;

    protected: 

    public: System::Windows::Forms::Label^  timer1;

    private:
        /// <summary>
        /// Required designer variable.
        /// </summary>
        System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        void InitializeComponent(void)
        {
            this->timer1Progress = (gcnew System::Windows::Forms::ProgressBar());
            this->timer1 = (gcnew System::Windows::Forms::Label());
            this->SuspendLayout();
            // 
            // timer1Progress
            // 
            this->timer1Progress->ForeColor = System::Drawing::Color::Fuchsia;
            this->timer1Progress->Location = System::Drawing::Point(3, 12);
            this->timer1Progress->Maximum = 30000;
            this->timer1Progress->Name = L"timer1Progress";
            this->timer1Progress->Size = System::Drawing::Size(244, 18);
            this->timer1Progress->Style = System::Windows::Forms::ProgressBarStyle::Continuous;
            this->timer1Progress->TabIndex = 0;
            this->timer1Progress->Value = 10000;
            //
            //timer1
            //
            this->timer1->AutoSize = true;
            this->timer1->ForeColor = System::Drawing::Color::White;
            this->timer1->Location = System::Drawing::Point(253, 108);
            this->timer1->Name = L"Timer1";
            this->timer1->Size = System::Drawing::Size(34, 13);
            this->timer1->TabIndex = 9;
            this->timer1->Text = L"00.00";
            // 
            // cooldowns
            // 
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64)), 
                static_cast<System::Int32>(static_cast<System::Byte>(64)));
            this->ClientSize = System::Drawing::Size(294, 138);
            this->Controls->Add(this->Timer1);;
            this->Controls->Add(this->timer1Progress);
            this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
            this->Name = L"cooldowns";
            this->StartPosition = System::Windows::Forms::FormStartPosition::Manual;
            this->Text = L"cooldowns";
            this->TopMost = true;
            this->Load += gcnew System::EventHandler(this, &cooldowns::cooldowns_Load);
            this->ResumeLayout(false);
            this->PerformLayout();

        }
#pragma endregion

private: System::Void cooldowns_Load(System::Object^  sender, System::EventArgs^  e) {

         }
};
}

多くの試行錯誤の後に編集すると、問題は CDwin->Show(); を取り囲んでいるようです。ShowDialog(); に切り替えると、残念ながら、プログレスバーの値も更新されません。これがマルチスレッドの出番だと思います。

4

2 に答える 2

0

常に使用する最初のフォームとして、およびメソッドは、フォームを既に実行している場合にSystem::Windows::Forms::Application::Run(CDwin)のみ使用できます。Show()ShowDialog()

使用Run()すると、いくつかの問題が発生します。この関数は、フォームが閉じられた後にのみ何かを返します。つまり、コードの後のRun()コードは、フォームが閉じられるまで実行されません。

そのため、メイン関数でフォームを操作することを忘れる必要があります。たとえば「Form1」と「Form2」の 2 つのフォームを作成することをお勧めします (スレッドを使用する方法もありますが、こちらの方が簡単です)。

「Form1」を非表示のベースフォームとして使用し、タイマーのリフレッシュによるアプリケーションの更新に使用します。

ユーザーに表示されたフォームとして「Form2」を使用します。Show()これを行うには、またはを使用して「Form1」内で「Form2」を実行する必要がありますShowDialog()

つまり、次のことを意味します。

// This is Form1 or base.
#include "Form2.h"
Form2 ^openForm2 = gcnew Form2();
openForm2->Show();
// while(true) Refresh the other form and other codes...
于 2014-01-12T14:06:51.403 に答える
0

ShowDialogフォームにメッセージループがあるように使用し、「50ミリ秒ごと」のものをタイマーのイベントをリッスンするイベントハンドラーに入れる必要があると思いますTick

于 2013-10-02T13:05:18.947 に答える