<strike id="kiyse"></strike>
  • <tr id="kiyse"></tr>
  • <strike id="kiyse"></strike><samp id="kiyse"><tbody id="kiyse"></tbody></samp>
    <strike id="kiyse"><s id="kiyse"></s></strike>
    <tr id="kiyse"></tr>
    <noframes id="kiyse"><code id="kiyse"></code></noframes>
    <th id="kiyse"></th>
    <samp id="kiyse"></samp>
  • <th id="kiyse"><s id="kiyse"></s></th>
  • UWP程序用多頁面實(shí)現(xiàn)應(yīng)用實(shí)例多開

     2025-3-26     作者:楊陽     聯(lián)系作者    

    Windows 10 IoT ARM64平臺(tái)下,UWP應(yīng)用和MFC程序不一樣,同時(shí)只能打開一個(gè)應(yīng)用實(shí)例。以串口程序?yàn)槔绻脩粝M瑫r(shí)打開多個(gè)應(yīng)用實(shí)例,一個(gè)應(yīng)用實(shí)例打開串口1,一個(gè)應(yīng)用實(shí)例打開串口2,那么我們可以加載多個(gè)頁面,在各個(gè)頁面分別加載功能模塊,實(shí)現(xiàn)程序功能模塊多開。

    本文以UWP串口例程為例,介紹如何用代碼實(shí)現(xiàn)同時(shí)打開多個(gè)串口模塊頁面,進(jìn)行測試。


     1、創(chuàng)建UWP工程 

    1. 打開visual studio 2022,點(diǎn)擊“創(chuàng)建新項(xiàng)目”。

    2. 選擇篩選條件,語言C++,平臺(tái)選擇Windows,應(yīng)用類型選擇UWP。

    3.  選擇“空白應(yīng)用”,本文以C++/CX為例。



     2、導(dǎo)入需要多開的功能模塊頁面 

    1.  創(chuàng)建工程后,右鍵點(diǎn)擊工程->添加->新建項(xiàng)。

    8.png


    2. 選擇XAML空白頁,給頁面命名為SerialPage.xaml,點(diǎn)擊添加。

    9.png


    3.  在工程中可以看到添加的頁面SerialPage,將之前寫好的UWP串口程序代碼COPY過來(參考文章《UWP串口程序開發(fā)》),把串口程序的xaml內(nèi)容拷貝到SerialPage.xaml中,把代碼文件.xaml.h和.xaml.cpp的內(nèi)容也拷貝到對應(yīng)文件SerialPage.xaml.h和SerialPage.xaml.cpp中。如果原UWP程序頁面名稱(默認(rèn)為MainPage)和當(dāng)前工程名稱(SerialPage)不一樣,注意全部替換一下。

    10.png


    4. 雙擊頁面SerialPage.xaml,檢查下是否添加成功。編譯一下,確認(rèn)代碼都正確COPY過來了。

     11.png



    3、通過Navigate加載新頁面 

    UWP中頁面Frame的概念,類似MFC中的窗口Dialog,但功能更強(qiáng)大些。主頁面可以打開新的子頁面,頁面本身也可以執(zhí)行跳轉(zhuǎn),回退操作。頁面的回收由系統(tǒng)負(fù)責(zé),當(dāng)沒有Content指向頁面后,頁面自動(dòng)被回收

    在主頁面中添加一個(gè)按鈕,按鈕中執(zhí)行代碼。

    Windows::UI::Xaml::Controls::Frame^ frame= new ref new Windows::UI::Xaml::Controls::Frame();
    frame->Navigate(TypeName(SerialPage::typeid));

    設(shè)置新頁面為當(dāng)前操作頁面。

    Window.Current.Content = frame;
    Window.Current.Activate();

    每點(diǎn)擊一次按鈕,就可以加載一個(gè)新的SerialPage頁面了。

     4、用導(dǎo)航控件SplitView管理多窗口 

    為了便于管理打開的新頁面,能在它們之間隨意切換,可以使用SplitView控件來實(shí)現(xiàn)。SplitView由一個(gè)導(dǎo)航區(qū)域和一個(gè)頁面區(qū)域組成,可以在導(dǎo)航區(qū)域Panel中添加不同按鈕,在點(diǎn)擊后,在頁面區(qū)域Content中顯示對應(yīng)的頁面。根據(jù)需求,可以設(shè)置導(dǎo)航區(qū)域大小,是否自動(dòng)隱藏等。

    1. 在主頁面中添加一個(gè)SplitView控件,命名為SplitViewMain。在它的Pane中可以用一個(gè)StackPanel來裝按鈕,給Content命名為FrameMain,在里面隨意加一段文字。

    <SplitView x:Name="SplitViewMain" DisplayMode="Inline" IsPaneOpen="True" >
        <SplitView.Pane>
            <StackPanel x:Name="BtnContainer">
            </StackPanel>
        </SplitView.Pane>
        <SplitView.Content>
            <Frame x:Name="FrameMain">
                <TextBlock Text="未添加測試接口" VerticalAlignment="Center" HorizontalAlignment="Center"/>
            </Frame>
        </SplitView.Content>
    </SplitView>


    2. 在Pane中添加幾個(gè)按鈕,可以加到StackPanel中,讓StackPanel來自動(dòng)排列。

    <SplitView.Pane>
        <StackPanel x:Name="BtnContainer">
            <Button Content="Button1" Click="Button1_Click"/>
            <Button Content="Button2" Click="Button2_Click"/>
        </StackPanel>
    </SplitView.Pane>


    3. 在按鈕中加入代碼

    void SPT::MainPage:: Button1_Click (Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
    {
           if (m_frame[0] == nullptr)
           {
                  m_frame[0] = ref new Windows::UI::Xaml::Controls::Frame();
    m_frame[0]->Navigate(TypeName(SerialPage::typeid));           //指定SerialPage
           }
           FrameMain = m_frame[0];
           SplitViewMain->Content = FrameMain;
    }

    這樣,就可以通過點(diǎn)擊不同按鈕,進(jìn)入對應(yīng)的頁面了

     5、動(dòng)態(tài)管理導(dǎo)航控件SplitView內(nèi)導(dǎo)航按鈕 

    有時(shí)候,如果導(dǎo)航按鈕的數(shù)量不確定,希望根據(jù)實(shí)際情況添加或刪除導(dǎo)航按鈕。本文例程中,每點(diǎn)擊一次添加按鈕,便添加一個(gè)串口測試頁面,做法如下。

    1. 在主頁面中添加一個(gè)按鈕,點(diǎn)擊一次,便在SplitView的Pane里加入一個(gè)按鈕,給這個(gè)按鈕設(shè)置參數(shù)Tag,便于區(qū)分不同按鈕。給按鈕綁定點(diǎn)擊響應(yīng)函數(shù)OnClick。

    void SPT::MainPage::BtnSerial_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
    {
           Button^ newButton;
           newButton = ref new Button;
    m_Count++;
           newButton->Tag = m_Count;
           newButton->Click += ref new Windows::UI::Xaml::RoutedEventHandler(this, &SPT::MainPage::OnClick);
           BtnContainer->Children->Append(newButton);
           m_frame[m_Count] = ref new Windows::UI::Xaml::Controls::Frame();
           m_frame[m_Count]->Navigate(TypeName(SerialPage::typeid));
           FrameMain = m_frame[m_Count];
           SplitViewMain->Content = FrameMain;
    }


    2. 在按鈕的響應(yīng)函數(shù)中讀出按鈕參數(shù),根據(jù)不同的參數(shù)決定如何處理,加載哪個(gè)頁面。

    void SPT::MainPage::OnClick(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
    {
           Button^ clickButton = safe_cast<Button^>(sender);
           int id = safe_cast<int>(clickButton->Tag);
          
           if (m_frame[id] == nullptr)
           {
                  return;
           }
           FrameMain = m_frame[id];
           SplitViewMain->Content = FrameMain;
    }

     


    6、主頁面與導(dǎo)航打開的新頁面之間數(shù)據(jù)通信 

    目前導(dǎo)航頁面和加載的子頁面相對獨(dú)立,很多時(shí)候主界面需要傳遞數(shù)據(jù)給子頁面,便于子頁面初始化,甚至需要給子頁面提供函數(shù)接口。子頁面退出時(shí)也需要回調(diào)函數(shù)通知主頁面,并返回處理后的數(shù)據(jù)。

    本文串口例程中

    1. 設(shè)置一個(gè)數(shù)據(jù)結(jié)構(gòu),把所有主頁面要傳輸?shù)臄?shù)據(jù)打包到這個(gè)數(shù)據(jù)接口中。文本例程中打包數(shù)據(jù)包括子頁面ID,和一個(gè)回調(diào)接口。

    public ref class PageData sealed : public Platform::Object
    {
    public:
           PageData(int initValue, Windows::Foundation::EventHandler<int>^ callback)
                  : _initValue(initValue), _exitCallback(callback){}
           property int InitValue {int get() { return _initValue; }}
           property Windows::Foundation::EventHandler<int>^ ExitCallback {
                  Windows::Foundation::EventHandler<int>^ get() { return _exitCallback; }
           }
    private:
           int _initValue;
           Windows::Foundation::EventHandler<int>^ _exitCallback;
    };


    2. 在主頁面加載子頁面時(shí),將打包數(shù)據(jù)一起傳過去,修改Navigate調(diào)用。

    m_frame[i] = ref new Windows::UI::Xaml::Controls::Frame();
    auto exitHandler = ref new Windows::Foundation::EventHandler<int>(
           this, &MainPage::OnPageExit);
    auto data = ref new PageData(i, exitHandler);
    m_frame[i]->Navigate(TypeName(SerialPage::typeid), data);
    FrameMain = m_frame[i];
    SplitViewMain->Content = FrameMain;


    3. 子頁面SerialPage重載OnNavigatedTo函數(shù),添加初始化代碼

    virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
    Windows::Foundation::EventHandler<int>^ m_ExitCallback;
     
    void SerialPage::OnNavigatedTo(NavigationEventArgs^ e)
    {
           auto data = dynamic_cast<PageData^>(e->Parameter);
           if (data != nullptr)
           {
                  m_id = data->InitValue;
                  m_ExitCallback = data->ExitCallback;
           }
    }


    4. 子頁面退出時(shí)調(diào)用回調(diào)函數(shù),傳回參數(shù)頁面ID

    void SPT::SerialPage::BtnExit_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
    {
           try
           {
                  CancelReadTask();
                  ClosePort();
           }
           catch (Platform::Exception^ ex)
           {
           }
           if (Frame->CanGoBack)
           {
                  Frame->GoBack();
           }
           Frame->Content = nullptr;
           if (m_ExitCallback != nullptr)
           {
                  m_ExitCallback->Invoke(this, m_id);
           }
    }


    5. 主頁面處理回調(diào)函數(shù)

    void SPT::MainPage::OnPageExit(Platform::Object^ sender, int id)
    {
       for (int i = 0; i < BtnContainer->Children->Size; ++i)
       {
          if (Button^ btn = dynamic_cast<Button^>(BtnContainer->Children->GetAt(i)))
          {
              if (btn->Tag != nullptr && safe_cast<int>(btn->Tag) == id)
              {
                   BtnContainer->Children->RemoveAt(i);
                   return;
              }
           }
       }
    }



     7、界面優(yōu)化 

    調(diào)整控件的邊界Margin,用LinearGradientBrush設(shè)置頁面及控件背景色,在代碼中適當(dāng)調(diào)整控件字體樣式,使得界面滿足設(shè)計(jì)需求。



     8、調(diào)試 

    打開Win10 IoT板子上的調(diào)試助手。

    3.png

    選擇工程平臺(tái)為ARM64,編譯運(yùn)行,示例如下。

    12.png

    需要程序源碼可以聯(lián)系英創(chuàng)工程師獲得。

    国产乱码精品一区二区三区香蕉 | 久久久WWW成人免费精品| 久久亚洲精品中文字幕| 青青青青久久精品国产h久久精品五福影院1421 | 亚洲精品国产电影| 亚洲精品无码少妇30P| 国产a∨精品一区二区三区不卡| 国产精品福利午夜在线观看| 91自产拍在线观看精品| 99精品在线播放| 国产成人精品视频一区| 国产乱子精品免费视观看片| 九九线精品视频在线观看| 超碰97久久国产精品牛牛| 2021国内精品久久久久影院| 中文字幕无码精品三级在线电影| 国产模特众筹精品视频| 无码精品国产dvd在线观看9久| 久久精品夜色国产亚洲av| 国产乱子伦精品无码专区| 精品久久国产视频| 最新露脸国产精品视频| 99j久久精品久久久久久| 久久久精品免费国产四虎| 国产精品原创巨作?v网站| 国产成品精品午夜视频| 免费无码精品黄AV电影| 69pao精品视频在线观看| 四虎国产成人永久精品免费| 99久久婷婷免费国产综合精品| 亚洲国产精品国产自在在线| 国产精品亚洲а∨无码播放不卡| 亚洲精品永久在线观看| 国产精品2019| 色妞妞www精品视频| 2021国产精品露脸在线| 99国产精品99久久久久久| 久久国产精品只做精品| 久久精品国产免费| 亚洲精品高清国产一线久久| 97久久精品国产精品青草|