激情综合丁香-激情综合六月-激情综合婷婷亚洲图片-激情综合图区-激情综合网五月

UWP程序用多頁面實現應用實例多開

 2025-3-26     作者:楊陽     聯系作者    

Windows 10 IoT ARM64平臺下,UWP應用和MFC程序不一樣,同時只能打開一個應用實例。以串口程序為例,如果用戶希望同時打開多個應用實例,一個應用實例打開串口1,一個應用實例打開串口2,那么我們可以加載多個頁面,在各個頁面分別加載功能模塊,實現程序功能模塊多開。

本文以UWP串口例程為例,介紹如何用代碼實現同時打開多個串口模塊頁面,進行測試。


 1、創建UWP工程 

1. 打開visual studio 2022,點擊“創建新項目”。

2. 選擇篩選條件,語言C++,平臺選擇Windows,應用類型選擇UWP。

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



 2、導入需要多開的功能模塊頁面 

1.  創建工程后,右鍵點擊工程->添加->新建項。

8.png


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

9.png


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

10.png


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

 11.png



3、通過Navigate加載新頁面 

UWP中頁面Frame的概念,類似MFC中的窗口Dialog,但功能更強大些。主頁面可以打開新的子頁面,頁面本身也可以執行跳轉,回退操作。頁面的回收由系統負責,當沒有Content指向頁面后,頁面自動被回收

在主頁面中添加一個按鈕,按鈕中執行代碼。

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

設置新頁面為當前操作頁面。

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

每點擊一次按鈕,就可以加載一個新的SerialPage頁面了。

 4、用導航控件SplitView管理多窗口 

為了便于管理打開的新頁面,能在它們之間隨意切換,可以使用SplitView控件來實現。SplitView由一個導航區域和一個頁面區域組成,可以在導航區域Panel中添加不同按鈕,在點擊后,在頁面區域Content中顯示對應的頁面。根據需求,可以設置導航區域大小,是否自動隱藏等。

1. 在主頁面中添加一個SplitView控件,命名為SplitViewMain。在它的Pane中可以用一個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中添加幾個按鈕,可以加到StackPanel中,讓StackPanel來自動排列。

<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;
}

這樣,就可以通過點擊不同按鈕,進入對應的頁面了

 5、動態管理導航控件SplitView內導航按鈕 

有時候,如果導航按鈕的數量不確定,希望根據實際情況添加或刪除導航按鈕。本文例程中,每點擊一次添加按鈕,便添加一個串口測試頁面,做法如下。

1. 在主頁面中添加一個按鈕,點擊一次,便在SplitView的Pane里加入一個按鈕,給這個按鈕設置參數Tag,便于區分不同按鈕。給按鈕綁定點擊響應函數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. 在按鈕的響應函數中讀出按鈕參數,根據不同的參數決定如何處理,加載哪個頁面。

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、主頁面與導航打開的新頁面之間數據通信 

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

本文串口例程中

1. 設置一個數據結構,把所有主頁面要傳輸的數據打包到這個數據接口中。文本例程中打包數據包括子頁面ID,和一個回調接口。

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. 在主頁面加載子頁面時,將打包數據一起傳過去,修改Navigate調用。

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函數,添加初始化代碼

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. 子頁面退出時調用回調函數,傳回參數頁面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. 主頁面處理回調函數

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、界面優化 

調整控件的邊界Margin,用LinearGradientBrush設置頁面及控件背景色,在代碼中適當調整控件字體樣式,使得界面滿足設計需求。



 8、調試 

打開Win10 IoT板子上的調試助手。

3.png

選擇工程平臺為ARM64,編譯運行,示例如下。

12.png

需要程序源碼可以聯系英創工程師獲得。

主站蜘蛛池模板: 26uuu久久| 日韩一区二区不卡中文字幕| 黄色免费观看视频网站| 又黄又爽一线毛片免费观看| 免费看的黄色| 高清性色生活片免费观看| 久久久久草| 中文字幕亚洲无线码| 中文字幕一区视频| 欧美一级特毛片| japanese色系国产在线高清| 天堂久久久久va久久久久| 一级亚洲| 亚洲成在人天堂一区二区| 国产caonila在线观看| 黄色短片免费看| 国内精品第一页| 亚洲丶国产丶欧美一区二区三区| 久久一区二区三区精品| 亚洲第一视频网| 国产a三级三级三级| 香蕉tv亚洲专区在线观看| 国产精品欧美日韩一区二区| 日韩精品久久一区二区三区| chinese麻豆自制国产| 中文字幕日韩精品亚洲七区| 乱人xxx国语对白91| 国产农村乱色xxxx| 黑人巨大系列在线播放| 激情亚洲视频| 久久亚| 亚洲第一久久| 亚洲女人网| 99久久久久国产| 天堂毛片| 片成年免费观看网站黄| 色婷婷综合欧美成人| 国产一级爱片| 国产精品一区三区| 黄色永久网站| 麻豆国产果冻传媒网站入口|