improve:窗口置顶

This commit is contained in:
2025-09-06 13:58:49 +08:00
parent 9081aea926
commit 67e3d51106
7 changed files with 232 additions and 73 deletions
+53 -3
View File
@@ -70,7 +70,32 @@ namespace Ink_Canvas.Helpers
try
{
if (PPTApplication == null || !Marshal.IsComObject(PPTApplication)) return false;
return PPTApplication.SlideShowWindows?.Count > 0;
// 检查是否有放映窗口
var slideShowWindows = PPTApplication.SlideShowWindows;
if (slideShowWindows == null || slideShowWindows.Count == 0) return false;
// 验证放映窗口是否真正有效
try
{
var slideShowWindow = slideShowWindows[1];
if (slideShowWindow == null) return false;
// 尝试访问放映窗口的属性来验证其有效性
var _ = slideShowWindow.View;
return true;
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x8001010E || hr == 0x80004005)
{
// COM对象已失效,触发断开连接
DisconnectFromPPT();
}
LogHelper.WriteLogToFile($"验证PPT放映窗口失败: {comEx.Message} (HR: 0x{hr:X8})", LogHelper.LogType.Warning);
return false;
}
}
catch (COMException comEx)
{
@@ -80,10 +105,12 @@ namespace Ink_Canvas.Helpers
// COM对象已失效,触发断开连接
DisconnectFromPPT();
}
LogHelper.WriteLogToFile($"检查PPT放映状态失败: {comEx.Message} (HR: 0x{hr:X8})", LogHelper.LogType.Warning);
return false;
}
catch
catch (Exception ex)
{
LogHelper.WriteLogToFile($"检查PPT放映状态时发生意外错误: {ex}", LogHelper.LogType.Warning);
return false;
}
}
@@ -452,7 +479,30 @@ namespace Ink_Canvas.Helpers
{
CurrentPresentation = activePresentation;
CurrentSlides = CurrentPresentation.Slides;
SlidesCount = CurrentSlides.Count;
// 验证页数读取是否成功
try
{
var slideCount = CurrentSlides.Count;
if (slideCount > 0)
{
SlidesCount = slideCount;
LogHelper.WriteLogToFile($"成功读取PPT页数: {slideCount}", LogHelper.LogType.Trace);
}
else
{
// 页数为0,可能是空演示文稿或读取失败
SlidesCount = 0;
LogHelper.WriteLogToFile("PPT演示文稿页数为0,可能为空演示文稿", LogHelper.LogType.Warning);
}
}
catch (COMException comEx)
{
// 页数读取失败
var hr = (uint)comEx.HResult;
SlidesCount = 0;
LogHelper.WriteLogToFile($"读取PPT页数失败: {comEx.Message} (HR: 0x{hr:X8})", LogHelper.LogType.Warning);
}
// 获取当前幻灯片
try
+33 -4
View File
@@ -81,10 +81,19 @@ namespace Ink_Canvas.Helpers
_mainWindow.BtnPPTSlideShow.Visibility = Visibility.Collapsed;
_mainWindow.BtnPPTSlideShowEnd.Visibility = Visibility.Visible;
// 只有在页数有效时才更新页码显示
if (currentSlide > 0 && totalSlides > 0)
{
_mainWindow.PPTBtnPageNow.Text = currentSlide.ToString();
_mainWindow.PPTBtnPageTotal.Text = $"/ {totalSlides}";
LogHelper.WriteLogToFile($"更新PPT页码显示: {currentSlide}/{totalSlides}", LogHelper.LogType.Trace);
}
else
{
// 页数无效时清空页码显示
_mainWindow.PPTBtnPageNow.Text = "?";
_mainWindow.PPTBtnPageTotal.Text = "/ ?";
LogHelper.WriteLogToFile($"PPT页数无效,清空页码显示: 当前页={currentSlide}, 总页数={totalSlides}", LogHelper.LogType.Warning);
}
UpdateNavigationPanelsVisibility();
@@ -113,8 +122,20 @@ namespace Ink_Canvas.Helpers
{
try
{
_mainWindow.PPTBtnPageNow.Text = currentSlide.ToString();
_mainWindow.PPTBtnPageTotal.Text = $"/ {totalSlides}";
// 只有在页数有效时才更新页码显示
if (currentSlide > 0 && totalSlides > 0)
{
_mainWindow.PPTBtnPageNow.Text = currentSlide.ToString();
_mainWindow.PPTBtnPageTotal.Text = $"/ {totalSlides}";
LogHelper.WriteLogToFile($"更新PPT页码显示: {currentSlide}/{totalSlides}", LogHelper.LogType.Trace);
}
else
{
// 页数无效时清空页码显示
_mainWindow.PPTBtnPageNow.Text = "?";
_mainWindow.PPTBtnPageTotal.Text = "/ ?";
LogHelper.WriteLogToFile($"PPT页数无效,清空页码显示: 当前页={currentSlide}, 总页数={totalSlides}", LogHelper.LogType.Warning);
}
}
catch (Exception ex)
{
@@ -156,17 +177,25 @@ namespace Ink_Canvas.Helpers
try
{
// 检查是否应该显示PPT按钮
// 不仅要检查按钮设置,还要确保确实在PPT放映模式下
// 不仅要检查按钮设置,还要确保确实在PPT放映模式下且页数有效
bool isInSlideShow = _mainWindow.PPTManager?.IsInSlideShow == true;
int slidesCount = _mainWindow.PPTManager?.SlidesCount ?? 0;
bool hasValidPageCount = slidesCount > 0;
bool shouldShowButtons = ShowPPTButton &&
_mainWindow.BtnPPTSlideShowEnd.Visibility == Visibility.Visible &&
_mainWindow.PPTManager?.IsInSlideShow == true;
isInSlideShow &&
hasValidPageCount;
if (!shouldShowButtons)
{
HideAllNavigationPanels();
LogHelper.WriteLogToFile($"隐藏PPT导航面板 - 放映状态: {isInSlideShow}, 页数: {slidesCount}, 按钮设置: {ShowPPTButton}", LogHelper.LogType.Trace);
return;
}
LogHelper.WriteLogToFile($"显示PPT导航面板 - 放映状态: {isInSlideShow}, 页数: {slidesCount}", LogHelper.LogType.Trace);
// 设置侧边按钮位置
_mainWindow.LeftSidePanelForPPTNavigation.Margin = new Thickness(0, 0, 0, PPTLSButtonPosition * 2);
_mainWindow.RightSidePanelForPPTNavigation.Margin = new Thickness(0, 0, 0, PPTRSButtonPosition * 2);
@@ -2,6 +2,7 @@ using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
@@ -13,6 +14,7 @@ using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Application = System.Windows.Application;
using Button = System.Windows.Controls.Button;
using Cursors = System.Windows.Input.Cursors;
@@ -946,10 +948,45 @@ namespace Ink_Canvas
var randWindow = new RandWindow(Settings);
randWindow.Show();
// 确保窗口显示后立即置顶
randWindow.Activate();
randWindow.Topmost = true;
randWindow.Focus();
// 使用延迟确保窗口完全显示后再强制置顶
randWindow.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
// 强制激活窗口
randWindow.Activate();
randWindow.Focus();
// 设置置顶
randWindow.Topmost = true;
// 使用Win32 API强制置顶
var hwnd = new WindowInteropHelper(randWindow).Handle;
if (hwnd != IntPtr.Zero)
{
const int WS_EX_TOPMOST = 0x00000008;
const int GWL_EXSTYLE = -20;
const int SWP_NOMOVE = 0x0002;
const int SWP_NOSIZE = 0x0001;
const int SWP_SHOWWINDOW = 0x0040;
const int SWP_NOOWNERZORDER = 0x0200;
var HWND_TOPMOST = new IntPtr(-1);
// 设置窗口样式为置顶
int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_TOPMOST);
// 强制置顶
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"强制置顶RandWindow失败: {ex.Message}", LogHelper.LogType.Error);
}
}), DispatcherPriority.Loaded);
}
public void CheckEraserTypeTab()
@@ -1346,7 +1383,9 @@ namespace Ink_Canvas
var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY);
// 计算浮动栏位置,考虑快捷调色盘的显示状态
double floatingBarWidth = ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX;
// 确保获取到正确的浮动栏宽度,如果ActualWidth为0则使用DesiredSize
double baseWidth = ViewboxFloatingBar.ActualWidth > 0 ? ViewboxFloatingBar.ActualWidth : ViewboxFloatingBar.DesiredSize.Width;
double floatingBarWidth = baseWidth * ViewboxFloatingBarScaleTransform.ScaleX;
// 如果快捷调色盘显示,确保有足够空间
if ((QuickColorPalettePanel != null && QuickColorPalettePanel.Visibility == Visibility.Visible) ||
@@ -1467,7 +1506,9 @@ namespace Ink_Canvas
var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY);
// 计算浮动栏位置,考虑快捷调色盘的显示状态
double floatingBarWidth = ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX;
// 确保获取到正确的浮动栏宽度,如果ActualWidth为0则使用DesiredSize
double baseWidth = ViewboxFloatingBar.ActualWidth > 0 ? ViewboxFloatingBar.ActualWidth : ViewboxFloatingBar.DesiredSize.Width;
double floatingBarWidth = baseWidth * ViewboxFloatingBarScaleTransform.ScaleX;
// 如果快捷调色盘显示,确保有足够空间
if ((QuickColorPalettePanel != null && QuickColorPalettePanel.Visibility == Visibility.Visible) ||
@@ -1549,7 +1590,9 @@ namespace Ink_Canvas
var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY);
// 计算浮动栏位置,考虑快捷调色盘的显示状态
double floatingBarWidth = ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX;
// 确保获取到正确的浮动栏宽度,如果ActualWidth为0则使用DesiredSize
double baseWidth = ViewboxFloatingBar.ActualWidth > 0 ? ViewboxFloatingBar.ActualWidth : ViewboxFloatingBar.DesiredSize.Width;
double floatingBarWidth = baseWidth * ViewboxFloatingBarScaleTransform.ScaleX;
// 如果快捷调色盘显示,确保有足够空间
if ((QuickColorPalettePanel != null && QuickColorPalettePanel.Visibility == Visibility.Visible) ||
+15 -7
View File
@@ -197,14 +197,22 @@ namespace Ink_Canvas
val > 0.5 && val < 1.25 ? val : val <= 0.5 ? 0.5 : val >= 1.25 ? 1.25 : 1;
ViewboxFloatingBarScaleTransform.ScaleY =
val > 0.5 && val < 1.25 ? val : val <= 0.5 ? 0.5 : val >= 1.25 ? 1.25 : 1;
// auto align - 新增:只在屏幕模式下重新计算浮动栏位置
if (currentMode == 0)
// 等待UI更新后再重新计算浮动栏位置,确保居中计算准确
Dispatcher.BeginInvoke(new Action(() =>
{
if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible)
ViewboxFloatingBarMarginAnimation(60);
else
ViewboxFloatingBarMarginAnimation(100, true);
}
// 强制更新布局以确保ActualWidth正确
ViewboxFloatingBar.UpdateLayout();
// auto align - 新增:只在屏幕模式下重新计算浮动栏位置
if (currentMode == 0)
{
if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible)
ViewboxFloatingBarMarginAnimation(60);
else
ViewboxFloatingBarMarginAnimation(100, true);
}
}), DispatcherPriority.Render);
}
private void ViewboxFloatingBarOpacityValueSlider_ValueChanged(object sender, RoutedEventArgs e)
+15 -51
View File
@@ -24,23 +24,11 @@
Margin="0,0,0,0" Visibility="Collapsed"
Foreground="#5B5D5F"
Text="00" FontSize="26"/>
<ItemsControl Name="TextControlHour" ItemsSource="{Binding ElementName=TextBlockHour, Path=Text}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Width="14">
<TextBlock Text="{Binding}" HorizontalAlignment="Center" FontWeight="SemiBold"
Foreground="{Binding ElementName=TextBlockHour, Path=Foreground}"
FontFamily="{Binding ElementName=TextBlockHour, Path=FontFamily}"
FontSize="{Binding ElementName=TextBlockHour, Path=FontSize}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Name="TextControlHour" Text="{Binding ElementName=TextBlockHour, Path=Text}"
FontFamily="{Binding ElementName=TextBlockHour, Path=FontFamily}"
Foreground="{Binding ElementName=TextBlockHour, Path=Foreground}"
FontSize="{Binding ElementName=TextBlockHour, Path=FontSize}"
FontWeight="SemiBold" HorizontalAlignment="Center"/>
<Grid Name="GridAdjustHour" Visibility="Visible" Margin="-29,-30,0,-30" Width="29">
<ui:SimpleStackPanel Spacing="2">
<Button Height="13" Width="{Binding ElementName=GridAdjustHour, Path=ActualWidth}" Click="Button_Click_1">
@@ -71,23 +59,11 @@
Margin="0,0,0,0" Visibility="Collapsed"
Foreground="{Binding ElementName=TextBlockHour, Path=Foreground}"
Text="01" FontSize="26"/>
<ItemsControl Name="TextControlMinute" ItemsSource="{Binding ElementName=TextBlockMinute, Path=Text}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Width="14">
<TextBlock Text="{Binding}" HorizontalAlignment="Center" FontWeight="SemiBold"
Foreground="{Binding ElementName=TextBlockMinute, Path=Foreground}"
FontFamily="{Binding ElementName=TextBlockMinute, Path=FontFamily}"
FontSize="{Binding ElementName=TextBlockMinute, Path=FontSize}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Name="TextControlMinute" Text="{Binding ElementName=TextBlockMinute, Path=Text}"
FontFamily="{Binding ElementName=TextBlockMinute, Path=FontFamily}"
Foreground="{Binding ElementName=TextBlockMinute, Path=Foreground}"
FontSize="{Binding ElementName=TextBlockMinute, Path=FontSize}"
FontWeight="SemiBold" HorizontalAlignment="Center"/>
<Grid Visibility="{Binding ElementName=GridAdjustHour, Path=Visibility}" Margin="-29,-30,0,-30" Width="29">
<ui:SimpleStackPanel Spacing="2">
<Button Height="13" Width="{Binding ElementName=GridAdjustHour, Path=ActualWidth}" Click="Button_Click_5">
@@ -130,23 +106,11 @@
Margin="0,0,0,0" Visibility="Collapsed"
Foreground="{Binding ElementName=TextBlockHour, Path=Foreground}"
Text="00" FontSize="26"/>
<ItemsControl Name="TextControlSecond" ItemsSource="{Binding ElementName=TextBlockSecond, Path=Text}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Width="14">
<TextBlock Text="{Binding}" HorizontalAlignment="Center" FontWeight="SemiBold"
Foreground="{Binding ElementName=TextBlockSecond, Path=Foreground}"
FontFamily="{Binding ElementName=TextBlockSecond, Path=FontFamily}"
FontSize="{Binding ElementName=TextBlockSecond, Path=FontSize}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Name="TextControlSecond" Text="{Binding ElementName=TextBlockSecond, Path=Text}"
FontFamily="{Binding ElementName=TextBlockSecond, Path=FontFamily}"
Foreground="{Binding ElementName=TextBlockSecond, Path=Foreground}"
FontSize="{Binding ElementName=TextBlockSecond, Path=FontSize}"
FontWeight="SemiBold" HorizontalAlignment="Center"/>
<Grid Margin="-96.8,0,0,0" Width="96.8" Background="Transparent" MouseUp="Grid_MouseUp"/>
<Grid Visibility="{Binding ElementName=GridAdjustHour, Path=Visibility}" Margin="-29,-30,0,-30" Width="29">
<ui:SimpleStackPanel Spacing="2">
+1 -1
View File
@@ -71,7 +71,7 @@
</Viewbox>
</ui:SimpleStackPanel>
</ScrollViewer>
<Viewbox Visibility="{Binding ElementName=BigViewController, Path=Visibility}" Margin="20,20,20,20" HorizontalAlignment="Right">
<Viewbox Margin="20,20,20,20" HorizontalAlignment="Right">
<ui:SimpleStackPanel Height="180" Orientation="Horizontal">
<Border x:Name="BtnFullscreen" MouseUp="BtnFullscreen_MouseUp" HorizontalAlignment="Right" VerticalAlignment="Bottom"
Margin="5"
+65
View File
@@ -5,11 +5,14 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using MessageBox = iNKORE.UI.WPF.Modern.Controls.MessageBox;
namespace Ink_Canvas
@@ -35,6 +38,9 @@ namespace Ink_Canvas
// 添加窗口关闭事件处理
Closed += RandWindow_Closed;
// 添加窗口显示事件处理,确保置顶
Loaded += RandWindow_Loaded;
}
private void LoadBackground(Settings settings)
@@ -86,6 +92,9 @@ namespace Ink_Canvas
// 添加窗口关闭事件处理
Closed += RandWindow_Closed;
// 添加窗口显示事件处理,确保置顶
Loaded += RandWindow_Loaded;
new Thread(() =>
{
@@ -349,6 +358,51 @@ namespace Ink_Canvas
}
}
/// <summary>
/// 窗口加载事件处理
/// </summary>
private void RandWindow_Loaded(object sender, RoutedEventArgs e)
{
// 使用延迟确保窗口完全加载后再应用置顶
Dispatcher.BeginInvoke(new Action(() =>
{
try
{
// 强制激活窗口
Activate();
Focus();
// 设置置顶
Topmost = true;
// 使用Win32 API强制置顶
var hwnd = new WindowInteropHelper(this).Handle;
if (hwnd != IntPtr.Zero)
{
const int WS_EX_TOPMOST = 0x00000008;
const int GWL_EXSTYLE = -20;
const int SWP_NOMOVE = 0x0002;
const int SWP_NOSIZE = 0x0001;
const int SWP_SHOWWINDOW = 0x0040;
const int SWP_NOOWNERZORDER = 0x0200;
var HWND_TOPMOST = new IntPtr(-1);
// 设置窗口样式为置顶
int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_TOPMOST);
// 强制置顶
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"RandWindow置顶失败: {ex.Message}", LogHelper.LogType.Error);
}
}), DispatcherPriority.Loaded);
}
/// <summary>
/// 窗口关闭事件处理
/// </summary>
@@ -357,5 +411,16 @@ namespace Ink_Canvas
// 窗口关闭时的清理工作
// 这里可以添加必要的清理代码
}
#region Win32 API
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
[DllImport("user32.dll")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
#endregion
}
}