You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NSIS自定义页面切换时闪烁现象的解决方法咨询

NSIS自定义页面切换时控件闪烁重绘的解决方法

问题描述

我创建了若干NSIS自定义页面,每个页面的自定义函数中执行nsDialogs::Create~nsDialogs::Show操作,每隔几个页面调用LoadBannerImage函数在固定位置加载横幅图片。已尝试lockWindow开关操作,但点击页面的上一页/下一页按钮时,横幅图片及其他控件均会闪烁重绘,该现象在低配虚拟机环境中更为明显,请问如何更自然地解决此问题?

现有代码片段

主脚本页面定义

Page custom DisplayWelcomePage
Page custom DisplayInstallationDirPage LeaveInstDirPage
!define MUI_PAGE_CUSTOMFUNCTION_SHOW InstallPage
!insertmacro MUI_PAGE_INSTFILES
Page custom DisplayInstallationFinishPage

WelcomePage.nsi 代码

;WelcomePage.nsi file

Function DisplayWelcomePage
nsDialogs::Create 1044
Pop $r0
SetCtlColors $r0 0 0xF5F5F5
Push $r0

Call LoadBannerImage
nsDialogs::Show
FunctionEnd

InstallationDirPage.nsi 代码

; InstallReadyPage.nsi file

Function DisplayInstallationDirPage 
nsDialogs::Create 1044
Pop $r0
SetCtlColors $r0 0 0xF5F5F5
Push $r0
Call LoadBannerImage

nsDialogs::Show
FunctionEnd

LoadBannerImage 函数

Function LoadBannerImage
    ${NSD_CreateBitmap} 0u 0u 100u 434u ""
    Pop $BannerImage
    SetCtlColors $BannerImage 0 0xF5F5F5
    ${NSD_SetBitmap} $BannerImage ${TempBannerFilePath} $8
FunctionEnd

解决方法

1. 复用全局位图控件,避免重复创建

每次切换页面都新建位图控件是闪烁的核心原因之一,改为全局初始化一次控件,切换页面时仅更新内容或控制显隐:

  • 定义全局变量存储控件句柄:
Var g_hBannerBitmap
  • 在安装初始化阶段创建全局位图控件:
Function .onInit
    ; 以NSIS主窗口为父控件创建位图
    ${NSD_CreateBitmap} 0u 0u 100u 434u ""
    Pop $g_hBannerBitmap
    SetCtlColors $g_hBannerBitmap 0 0xF5F5F5
    ; 默认隐藏,需要显示的页面再调用显示
    ShowWindow $g_hBannerBitmap ${SW_HIDE}
FunctionEnd
  • 修改LoadBannerImage函数,仅更新图片并显示:
Function LoadBannerImage
    ${NSD_SetBitmap} $g_hBannerBitmap ${TempBannerFilePath} $8
    ShowWindow $g_hBannerBitmap ${SW_SHOW}
FunctionEnd
  • 在不需要横幅的页面中隐藏控件:
Function SomePageWithoutBanner
    nsDialogs::Create 1044
    Pop $r0
    ; ...其他页面逻辑
    ShowWindow $g_hBannerBitmap ${SW_HIDE}
    nsDialogs::Show
FunctionEnd

2. 开启窗口双缓冲

通过Windows API为页面窗口开启双缓冲,减少重绘闪烁:
在每个自定义页面的nsDialogs::Create之后添加以下代码:

; 开启WS_EX_COMPOSITED扩展样式实现双缓冲
GetWindowLong $r0 ${GWL_EXSTYLE}
IntOp $r0 $r0 | 0x02000000 ; 直接使用WS_EX_COMPOSITED的数值
SetWindowLong $r0 ${GWL_EXSTYLE} $r0

3. 延迟图片加载时机

将图片加载延迟到窗口初始化完成后执行,避免与页面控件初始化冲突:

Function DisplayWelcomePage
nsDialogs::Create 1044
Pop $r0
SetCtlColors $r0 0 0xF5F5F5
; 监听WM_INITDIALOG消息,窗口初始化完成后再加载图片
nsDialogs::OnNotify $r0 ${WM_INITDIALOG} OnWelcomePageInit
Push $r0

nsDialogs::Show
FunctionEnd

Function OnWelcomePageInit
    Call LoadBannerImage
FunctionEnd

4. 预加载图片到内存

提前将图片加载到内存,避免每次切换页面都从磁盘读取:

Var g_hBannerMemBitmap

Function .onInit
    ; 预加载图片到内存
    System::Call 'user32.dll::LoadImage(i0, t "${TempBannerFilePath}", i0, i0, i0, i0x10)'
    Pop $g_hBannerMemBitmap
FunctionEnd

; 修改LoadBannerImage使用内存位图
Function LoadBannerImage
    SendMessage $g_hBannerBitmap ${STM_SETIMAGE} ${IMAGE_BITMAP} $g_hBannerMemBitmap
    ShowWindow $g_hBannerBitmap ${SW_SHOW}
FunctionEnd

内容的提问来源于stack exchange,提问作者tux Neoh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 18:15:08