initial: nsAdvsplash plugin 1.0.0

This commit is contained in:
2026-04-29 23:19:37 +02:00
commit 889289e5a0
36 changed files with 3329 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 4
[*.{yml,yaml,json}]
indent_size = 2
[*.md]
trim_trailing_whitespace = false
[*.{cmd,bat,ps1}]
end_of_line = crlf
[*.{nsi,nsh,sln,vcxproj,filters}]
end_of_line = crlf
[Makefile]
indent_style = tab
+52
View File
@@ -0,0 +1,52 @@
# Normalizzazione line endings
* text=auto eol=lf
# File di codice
*.c text eol=lf
*.cpp text eol=lf
*.h text eol=lf
*.hpp text eol=lf
*.def text eol=lf
*.py text eol=lf
*.ps1 text eol=lf
*.cmd text eol=crlf
*.bat text eol=crlf
# NSIS
*.nsi text eol=crlf
*.nsh text eol=crlf
# Markdown / docs / config
*.md text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.json text eol=lf
*.txt text eol=lf
*.xml text eol=lf
# Visual Studio (CRLF richiesto)
*.sln text eol=crlf
*.vcxproj text eol=crlf merge=union
*.filters text eol=crlf merge=union
*.rc binary
*.rc2 binary
# Binari
*.dll binary
*.exe binary
*.lib binary
*.obj binary
*.pdb binary
*.zip binary
*.7z binary
*.png binary
*.ico binary
*.gif binary
*.jpg binary
*.jpeg binary
*.bmp binary
*.pdf binary
# Linguistic detection (GitHub Linguist / Gitea analogo)
*.nsi linguist-language=NSIS
*.nsh linguist-language=NSIS
+76
View File
@@ -0,0 +1,76 @@
name: Bug Report
description: Segnala un bug riproducibile
title: "[Bug]: "
labels: ["bug", "triage"]
body:
- type: markdown
attributes:
value: |
Grazie per la segnalazione. Compila i campi sotto per aiutarci a riprodurre il problema.
- type: input
id: plugin-version
attributes:
label: Versione plugin
description: Contenuto del file VERSION o tag della release scaricata
placeholder: "1.6.0"
validations:
required: true
- type: dropdown
id: architecture
attributes:
label: Architettura DLL usata
options:
- x86-ansi
- x86-unicode
- amd64-unicode
- non so / multiple
validations:
required: true
- type: input
id: nsis-version
attributes:
label: Versione NSIS
placeholder: "3.10"
validations:
required: true
- type: input
id: os
attributes:
label: Sistema operativo
placeholder: "Windows 11 23H2 x64"
validations:
required: true
- type: textarea
id: repro
attributes:
label: Passi per riprodurre
description: Script .nsi minimale che riproduce il problema
render: nsis
validations:
required: true
- type: textarea
id: expected
attributes:
label: Comportamento atteso
validations:
required: true
- type: textarea
id: actual
attributes:
label: Comportamento osservato
description: Includi messaggi di errore esatti, output del log NSIS, screenshot
validations:
required: true
- type: textarea
id: additional
attributes:
label: Note aggiuntive
description: Qualunque altra informazione utile (workaround tentati, ecc.)
+8
View File
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Domande generali
url: https://gitea.emulab.it/Simone/nsis-plugin-nsadvsplash/issues?type=question
about: Per domande di utilizzo che non sono bug, apri una issue con label "question"
- name: Security
url: https://gitea.emulab.it/Simone/nsis-plugin-nsadvsplash/security/advisories/new
about: Segnala vulnerabilità di security in privato (non aprire issue pubbliche)
@@ -0,0 +1,32 @@
name: Feature Request
description: Suggerisci una nuova funzionalità o miglioramento
title: "[Feature]: "
labels: ["enhancement"]
body:
- type: textarea
id: problem
attributes:
label: Problema / Caso d'uso
description: Quale problema vorresti risolvere? Quale workflow vuoi abilitare?
validations:
required: true
- type: textarea
id: proposal
attributes:
label: Proposta
description: Come dovrebbe funzionare? Includi esempio di API/uso negli script NSIS se possibile.
render: nsis
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternative considerate
description: Altri approcci che hai valutato e perché sono stati scartati
- type: textarea
id: additional
attributes:
label: Note aggiuntive
+31
View File
@@ -0,0 +1,31 @@
## Descrizione
<!-- Descrivi cosa cambia questa PR e perché. Riferisci issue se applicabile (Closes #XXX). -->
## Tipo di Modifica
- [ ] Bug fix (modifica non breaking che risolve un problema)
- [ ] Feature (modifica non breaking che aggiunge funzionalità)
- [ ] Breaking change (fix o feature che rompe la compatibilità)
- [ ] Documentazione
- [ ] Build / CI
## Architetture Testate
- [ ] `x86-ansi`
- [ ] `x86-unicode`
- [ ] `amd64-unicode`
## Checklist
- [ ] Build completa senza warning: `python build_plugin.py`
- [ ] CHANGELOG.md aggiornato (sezione `[Unreleased]`)
- [ ] README / docs aggiornati se l'API è cambiata
- [ ] Esempi aggiornati se l'API è cambiata
- [ ] Conventional Commits rispettato
- [ ] Nessun file in `dist/` o `__pycache__/` committato
- [ ] Self-review completata
## Note Aggiuntive
<!-- Eventuali considerazioni per i reviewer, screenshot, output di test, ecc. -->
+66
View File
@@ -0,0 +1,66 @@
# Build (GitHub) — pipeline CI primaria
#
# Strategia hosting:
# - Repo primario su Gitea (push iniziale)
# - Push mirror automatico Gitea -> GitHub
# - GitHub esegue TUTTA la CI (Gitea non esegue Actions)
#
# Trigger:
# - push su main (incluso quello propagato dal mirror Gitea)
# - PR aperte su GitHub
# - run manuale via UI
name: Build
on:
push:
branches: [main]
paths-ignore:
- '**.md'
- 'docs/**'
- 'examples/**'
pull_request:
branches: [main]
workflow_dispatch:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
build:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
config: [x86-ansi, x86-unicode, x64-unicode]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v2
- name: Read VERSION
id: version
shell: pwsh
run: |
$v = (Get-Content VERSION -Raw).Trim()
"version=$v" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
- name: Build ${{ matrix.config }}
run: python build_plugin.py --config ${{ matrix.config }} --verbosity minimal
- name: Upload DLL
uses: actions/upload-artifact@v4
with:
name: ${{ github.event.repository.name }}-${{ steps.version.outputs.version }}-${{ matrix.config }}
path: dist/**
if-no-files-found: error
retention-days: 30
+99
View File
@@ -0,0 +1,99 @@
# Release (GitHub) — pipeline release primaria
#
# Triggerata quando un tag v* viene propagato dal mirror Gitea.
# Costruisce gli artifact per tutte le architetture e crea la GitHub Release.
name: Release
on:
push:
tags: ['v*']
workflow_dispatch:
inputs:
tag:
description: 'Tag versione (es. v1.7.0)'
required: true
permissions:
contents: write
jobs:
build:
runs-on: windows-latest
strategy:
fail-fast: true
matrix:
config: [x86-ansi, x86-unicode, x64-unicode]
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- uses: microsoft/setup-msbuild@v2
- name: Build ${{ matrix.config }}
run: python build_plugin.py --config ${{ matrix.config }}
- name: Determine version & arch
id: meta
shell: pwsh
run: |
$tag = "${{ github.ref_name }}"
if ([string]::IsNullOrEmpty($tag) -or $tag -eq "main") { $tag = "${{ inputs.tag }}" }
$v = $tag -replace '^v',''
$map = @{ 'x86-ansi' = 'x86-ansi'; 'x86-unicode' = 'x86-unicode'; 'x64-unicode' = 'amd64-unicode' }
$dir = $map['${{ matrix.config }}']
echo "version=$v" >> $env:GITHUB_OUTPUT
echo "tag=$tag" >> $env:GITHUB_OUTPUT
echo "dir=$dir" >> $env:GITHUB_OUTPUT
- name: Package
shell: pwsh
run: |
$name = "${{ github.event.repository.name }}-${{ steps.meta.outputs.version }}-${{ steps.meta.outputs.dir }}"
$stage = "stage/$name"
New-Item -ItemType Directory -Force -Path $stage | Out-Null
Copy-Item "dist/${{ steps.meta.outputs.dir }}/*" $stage -Recurse
Copy-Item README.md, LICENSE, VERSION, CHANGELOG.md $stage
if (Test-Path "include") { Copy-Item "include" $stage -Recurse }
if (Test-Path "examples") { Copy-Item "examples" $stage -Recurse }
Compress-Archive -Path "$stage/*" -DestinationPath "$name.zip" -Force
- uses: actions/upload-artifact@v4
with:
name: pkg-${{ matrix.config }}
path: '*.zip'
publish:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
- name: SHA256SUMS
run: |
cd artifacts
sha256sum *.zip > SHA256SUMS.txt
cat SHA256SUMS.txt
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
files: |
artifacts/*.zip
artifacts/SHA256SUMS.txt
generate_release_notes: true
body: |
**Repository primario**: vedi link Gitea nel README.
Il mirror GitHub è generato automaticamente dal repo Gitea (sorgente di verità).
Per issue e PR aprire ticket sul repository primario Gitea.
+63
View File
@@ -0,0 +1,63 @@
# Build output (src/ subdirs only — dist/ is tracked, contains pre-built DLLs)
bin/
obj/
Build/
build/
# Visual Studio
*.user
*.suo
*.ncb
*.sdf
.vs/
ipch/
*.VC.db
*.VC.VC.opendb
*.opendb
*.aps
*.tlog
*.idb
*.pdb
*.ilk
*.exp
*.lib
*.obj
# Python
__pycache__/
*.pyc
*.pyo
.pytest_cache/
*.egg-info/
.venv/
venv/
# Editor / IDE
.vscode/
.idea/
*.swp
*.swo
*~
# OS
Thumbs.db
desktop.ini
.DS_Store
# NSIS
*.nsh.bak
# Logs
*.log
.logs/
# Sensitive
.env
.env.local
*.pem
*.key
# Migration/automation scripts (temporary, contain tokens — never commit)
tools/t*.py
tools/check_*.py
tools/legacy/
+26
View File
@@ -0,0 +1,26 @@
# Changelog
Tutte le modifiche rilevanti a questo progetto sono documentate in questo file.
Il formato segue [Keep a Changelog](https://keepachangelog.com/it/1.0.0/),
e il progetto aderisce al [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [1.0.1] — 2026-04-29
### Changed
- Build script completamente riscritto: Colors, Spinner, BuildConfig, build parallelo con ThreadPoolExecutor, CPU info, output colorato OK/FAIL
- CI: rimosso flag `--verbose` (non esistente) in favore di `--verbosity minimal`
## [1.0.0] — 2026-04-29
### Added
- Prima release come repository indipendente
- Build script unificato (`build_plugin.py`) con CLI canonica
- CI/CD via GitHub Actions (mirror automatico Gitea → GitHub)
- Documentazione completa (README, CONTRIBUTING, SECURITY)
[Unreleased]: https://gitea.emulab.it/Simone/nsis-plugin-nsadvsplash/compare/v1.0.1...HEAD
[1.0.1]: https://gitea.emulab.it/Simone/nsis-plugin-nsadvsplash/compare/v1.0.0...v1.0.1
[1.0.0]: https://gitea.emulab.it/Simone/nsis-plugin-nsadvsplash/releases/tag/v1.0.0
+137
View File
@@ -0,0 +1,137 @@
# Contribuire a nsAdvsplash
Grazie per il tuo interesse a contribuire!
> Repository primario: [https://gitea.emulab.it/Simone/nsis-plugin-nsadvsplash](https://gitea.emulab.it/Simone/nsis-plugin-nsadvsplash)
> Mirror GitHub: [https://github.com/systempal/nsis-plugin-nsadvsplash](https://github.com/systempal/nsis-plugin-nsadvsplash) (read-only — apri PR su Gitea)
## Prerequisiti
| Strumento | Versione | Note |
|-----------|----------|------|
| Visual Studio | 2022 / 2026 | Workload: Desktop development with C++ (toolset v143/v145) |
| Python | 3.7+ | Per `build_plugin.py` |
| Git | 2.30+ | Con supporto submoduli se applicabile |
## Quick Start
```powershell
git clone https://gitea.emulab.it/Simone/nsis-plugin-nsadvsplash.git
cd nsis-plugin-nsadvsplash
python build_plugin.py
```
Output in `dist/{x86-ansi,x86-unicode,amd64-unicode}/`.
## Workflow Sviluppo
### 1. Branch
```powershell
git checkout -b feat/nome-feature # nuova feature
git checkout -b fix/descrizione-bug # bugfix
git checkout -b docs/aggiornamento # solo doc
git checkout -b chore/manutenzione # build, dipendenze
```
### 2. Commit
Segui [Conventional Commits](https://www.conventionalcommits.org/it/v1.0.0/):
```
feat: aggiunge supporto per formato XYZ
fix: corregge crash su Windows 11 ARM
docs: aggiorna esempio di utilizzo
chore: aggiorna toolset MSVC
refactor: estrae logica parsing in funzione separata
test: aggiunge test per edge case
build: aggiorna script di build
ci: aggiorna workflow GitHub Actions
```
Breaking changes:
```
feat!: rinomina API Foo() in Bar()
BREAKING CHANGE: Foo() rinominata in Bar(); aggiornare tutti i chiamanti.
```
### 3. Pull Request
PR aperte verso il branch `main` su Gitea. Verifica:
- [ ] Build completa senza warning per tutte le architetture: `python build_plugin.py`
- [ ] Esempi aggiornati se cambia l'API
- [ ] `CHANGELOG.md` aggiornato (sezione `[Unreleased]`)
- [ ] Documentazione aggiornata (README, docs/API.md se esiste)
- [ ] Conventional Commits rispettato
- [ ] Nessun file in `dist/` o `__pycache__/` committato
## Build Script
```
python build_plugin.py [opzioni]
```
| Opzione | Default | Descrizione |
|---------|---------|-------------|
| `--config` | `all` | Architettura: `x86-ansi`, `x86-unicode`, `x64-unicode`, `all` |
| `--toolset` | `auto` | Visual Studio: `2022`, `2026`, `auto` (rileva il più recente) |
| `--jobs` | numero CPU | Thread paralleli per la build |
| `--clean` | false | Pulisce `dist/` prima di compilare |
| `--install-dir` | none | Copia DLL anche in `<dir>/{arch}/` (es. NSIS plugin folder) |
| `--verbose` | false | Output dettagliato (mostra comandi MSBuild) |
Exit codes:
- `0` — Successo
- `1` — Errore di build
- `2` — Prerequisiti mancanti
- `3` — Argomenti invalidi
## Release Workflow
Le release sono automatiche via tag Git:
```powershell
# 1. Aggiorna VERSION e CHANGELOG.md
echo "1.7.0" > VERSION
# (modifica CHANGELOG.md spostando entry da [Unreleased] a [1.7.0])
# 2. Commit
git add VERSION CHANGELOG.md
git commit -m "chore(release): v1.7.0"
# 3. Tag annotato
git tag -a v1.7.0 -m "Release v1.7.0"
# 4. Push
git push origin main
git push origin v1.7.0
```
Il workflow `.github/workflows/release.yml` compilerà tutte le architetture
e creerà la release su Gitea con gli artifact ZIP allegati. Il mirror GitHub
riceverà automaticamente il tag.
## Code Style
- C/C++: stile coerente con il file modificato
- Python: PEP 8 (4 spazi indent, line length flessibile)
- Header file: `#include` ordinati: stdlib → Win32 → progetto
- Encoding: UTF-8 senza BOM (eccetto `.rc` che richiede UTF-16 LE)
- Line endings: LF in repo (`.gitattributes` normalizza)
## Reporting Bug
Apri una [issue](https://gitea.emulab.it/Simone/nsis-plugin-nsadvsplash/issues/new) usando il template "Bug Report".
Includi:
- Versione plugin e architettura DLL usata
- Versione NSIS
- Sistema operativo
- Script `.nsi` minimale che riproduce il problema
- Output / errore esatto
## Domande
Per domande generali, apri una [issue](https://gitea.emulab.it/Simone/nsis-plugin-nsadvsplash/issues) con label `question`.
+21
View File
@@ -0,0 +1,21 @@
zlib License
Copyright (c) 2026 Simone
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
+137
View File
@@ -0,0 +1,137 @@
# NewAdvSplash NSIS Plugin
**Personal modified version**
---
## Original Description
NewAdvSplash.dll - plug-in that lets you throw up a splash screen in NSIS installers with fading effects (win2k/xp) and transparency. At the same time can play wav-mp3 sound file.
## Usage
### 1) Show splash screen
```nsis
newadvsplash::show [/NOUNLOAD] Delay FadeIn FadeOut KeyColor [/BANNER] [/PASSIVE] [/NOCANCEL] FileName
```
**Parameters:**
- `Delay` - time (milliseconds) to show image
- `FadeIn` - time to show the fadein scene
- `FadeOut` - time to show the fadeout scene
- `KeyColor` - color used for transparency, could be any RGB value (for ex. R=255 G=100 B=16 -> KeyColor=0xFF6410). Use KeyColor=-1 if there is no transparent color at your image. If KeyColor=-2 and image type is gif, plug-in attempts to extract transparency color value from the file header. For gif images transparency on the static background works even if KeyColor=-1.
- `/BANNER` - returns control to installer immediately after plug-in activation. Not depends on installer page - parent window NULL.
- `/NOCANCEL` - disables 'exit on user click' default behaviour.
- `/PASSIVE` - not forces splash window to foreground.
- `FileName` - splash image filename (with extension!). Bmp, gif and jpg image types are supported.
**Examples:**
```nsis
newadvsplash::show 3000 0 0 -2 "$PLUGINSDIR\catch.gif"
```
```nsis
newadvsplash::show /NOUNLOAD 1000 600 400 0xFF6410 /BANNER "$TEMP\spltmp.bmp"
```
Use /NOUNLOAD with /BANNER key - this case plug-in not waits for the end of 'show' and returns control to installer. If used in .onInit function, /BANNER key requires 'ShowWindow $HWNDPARENT 2' in .onGUIInit
### 2) Stop splash
```nsis
newadvsplash::stop [/WAIT | /FADEOUT]
```
- Without options terminates banner.
- With `/WAIT` option waits for the end.
- With `/FADEOUT` option forces banner close with fade out effect ('Delay' -> 0).
### 3) Play sound
```nsis
newadvsplash::play /NOUNLOAD [/LOOP] FileName
```
- `FileName` - sound filename to play (with extension, wav, mp3 ...).
- Empty Filename string "" stops sound.
**Example:**
```nsis
newadvsplash::play /NOUNLOAD /LOOP "$PLUGINSDIR\snd.mp3"
newadvsplash::show 2000 1000 500 -1 "$PLUGINSDIR\iamfat.jpg"
```
### 4) Get window handle
```nsis
newadvsplash::hwnd /NOUNLOAD
Pop $0 ; $0 is window handle now
```
## Compatibility
- Basic - Win95 and later.
- Fadein/fadeout - win2k/winxp.
## Credits
- Original code - Justin
- Converted to a plugin DLL by Amir Szekely (kichik)
- Fading and transparency by Nik Medved (brainsucker)
- Gif and jpeg support, /BANNER and /CANCEL, mp3 support - Takhir Bedertdinov
---
## ⚠️ Differences in the Personal Version
### New supported architecture: x64 (amd64-unicode)
The original supported only:
- x86-ansi (Plugins\newadvsplash.dll)
- x86-unicode (Unicode\plugins\newadvsplash.dll)
The personal version adds support for:
- **amd64-unicode** (x64)
### Added Files
- `build_plugin.py` - Python script to compile the plugin for all architectures
- `src/exdll.h` - Header for the NSIS extern DLL API
- `src/NewAdvSplash.vcxproj` - Visual Studio project updated for VS2022 and x64
### Removed Files
Pre-compiled DLL files have been removed from the distribution as they are generated by the build:
- `Plugins/newadvsplash.dll`
- `Unicode/plugins/newadvsplash.dll`
### Build
```cmd
cd nsAdvsplash
python build_plugin.py
```
DLLs are copied to `dist/{platform}/newadvsplash.dll`.
### Build Options
```powershell
python build_plugin.py --config x86-unicode # Single architecture (x86-ansi|x86-unicode|x64-unicode|all)
python build_plugin.py --vs-version 2026 # Specific VS version (2022|2026|auto)
python build_plugin.py --clean # Clean dist/ before build
python build_plugin.py --install-dir "C:\NSIS\Plugins" # Copy to additional NSIS directory
python build_plugin.py --verbosity minimal # MSBuild verbosity (quiet|minimal|normal|detailed|diagnostic)
```
### Functional Changes
No functional changes compared to the original. Modifications are limited to the build infrastructure and x64 support.
---
*See [README_IT.md](README_IT.md) for the Italian version.*
+128
View File
@@ -0,0 +1,128 @@
# NewAdvSplash NSIS Plugin
**Versione personale modificata**
---
## Descrizione Originale
NewAdvSplash.dll - plug-in che permette di visualizzare uno splash screen negli installer NSIS con effetti di dissolvenza (win2k/xp) e trasparenza. Può contemporaneamente riprodurre file audio wav/mp3.
## Utilizzo
### 1) Mostra splash screen
```nsis
newadvsplash::show [/NOUNLOAD] Delay FadeIn FadeOut KeyColor [/BANNER] [/PASSIVE] [/NOCANCEL] FileName
```
**Parametri:**
- `Delay` - tempo (millisecondi) di visualizzazione dell'immagine
- `FadeIn` - tempo per la scena di fade in
- `FadeOut` - tempo per la scena di fade out
- `KeyColor` - colore usato per la trasparenza, può essere qualsiasi valore RGB (es. R=255 G=100 B=16 -> KeyColor=0xFF6410). Usare KeyColor=-1 se non c'è colore trasparente. Se KeyColor=-2 e il tipo è gif, il plug-in tenta di estrarre il colore di trasparenza dall'header del file.
- `/BANNER` - restituisce il controllo all'installer subito dopo l'attivazione del plug-in.
- `/NOCANCEL` - disabilita il comportamento default 'exit on user click'.
- `/PASSIVE` - non forza la finestra splash in primo piano.
- `FileName` - nome file immagine splash (con estensione!). Tipi supportati: Bmp, gif e jpg.
**Esempi:**
```nsis
newadvsplash::show 3000 0 0 -2 "$PLUGINSDIR\catch.gif"
```
```nsis
newadvsplash::show /NOUNLOAD 1000 600 400 0xFF6410 /BANNER "$TEMP\spltmp.bmp"
```
### 2) Ferma splash
```nsis
newadvsplash::stop [/WAIT | /FADEOUT]
```
- Senza opzioni termina il banner.
- Con `/WAIT` attende la fine.
- Con `/FADEOUT` forza la chiusura con effetto fade out.
### 3) Riproduci audio
```nsis
newadvsplash::play /NOUNLOAD [/LOOP] FileName
```
- `FileName` - file audio da riprodurre (con estensione, wav, mp3...).
- Stringa vuota "" ferma l'audio.
### 4) Ottieni handle finestra
```nsis
newadvsplash::hwnd /NOUNLOAD
Pop $0 ; $0 è ora l'handle della finestra
```
## Compatibilità
- Base - Win95 e successivi.
- Fadein/fadeout - win2k/winxp.
## Crediti
- Codice originale - Justin
- Convertito in plugin DLL da Amir Szekely (kichik)
- Dissolvenza e trasparenza di Nik Medved (brainsucker)
- Supporto gif e jpeg, /BANNER e /CANCEL, supporto mp3 - Takhir Bedertdinov
---
## ⚠️ Differenze nella versione personale
### Nuova architettura supportata: x64 (amd64-unicode)
L'originale supportava solo:
- x86-ansi (Plugins\newadvsplash.dll)
- x86-unicode (Unicode\plugins\newadvsplash.dll)
La versione personale aggiunge il supporto per:
- **amd64-unicode** (x64)
### File aggiunti
- `build_plugin.py` - Script Python per compilare il plugin per tutte le architetture
- `src/exdll.h` - Header per l'API NSIS extern DLL
- `src/NewAdvSplash.vcxproj` - Progetto Visual Studio aggiornato per VS2022 e x64
### File rimossi
I file DLL precompilati sono stati rimossi dalla distribuzione in quanto vengono generati dalla compilazione:
- `Plugins/newadvsplash.dll`
- `Unicode/plugins/newadvsplash.dll`
### Compilazione
```cmd
cd nsAdvsplash
python build_plugin.py
```
I DLL vengono copiati in `dist/{platform}/newadvsplash.dll`.
### Opzioni build
```powershell
python build_plugin.py --config x86-unicode # Solo un'architettura (x86-ansi|x86-unicode|x64-unicode|all)
python build_plugin.py --vs-version 2026 # Versione VS specifica (2022|2026|auto)
python build_plugin.py --clean # Pulizia dist/ prima della build
python build_plugin.py --install-dir "C:\NSIS\Plugins" # Copia in directory NSIS aggiuntiva
python build_plugin.py --verbosity minimal # Verbosità MSBuild (quiet|minimal|normal|detailed|diagnostic)
```
### Modifiche funzionali
Nessuna modifica funzionale rispetto all'originale. Le modifiche riguardano solo l'infrastruttura di build e il supporto x64.
---
*See [README.md](README.md) for the English version.*
+40
View File
@@ -0,0 +1,40 @@
# Security Policy
## Versioni Supportate
Solo l'ultima versione minor riceve fix di security.
| Versione | Supporto |
|----------|----------|
| Latest minor (es. 1.0.0) | ✅ |
| Versioni precedenti | ❌ |
## Reporting di una Vulnerabilità
**Non aprire issue pubbliche per vulnerabilità di security.**
Per segnalare una vulnerabilità:
1. **Preferito**: usa la funzione [Security Advisory privato](https://gitea.emulab.it/Simone/nsis-plugin-nsadvsplash/security/advisories/new) di Gitea
2. **Alternativa**: invia email a `security@example.com` (sostituire con email reale prima del primo release)
Includi:
- Descrizione della vulnerabilità
- Passi per riprodurla
- Versione/i affette
- Possibile mitigazione (se nota)
## Tempo di Risposta
- Acknowledgment iniziale: entro 7 giorni
- Valutazione: entro 14 giorni
- Patch (se confermata): tempistiche dipendono dalla severità
## Hardening
Questo plugin gira con i permessi del processo NSIS chiamante (tipicamente
l'utente che esegue l'installer). Non richiede privilegi elevati per la
compilazione né per l'esecuzione, salvo dove esplicitamente documentato.
DLL distribuite tramite Releases sono compilate da CI GitHub Actions con
toolchain pinnata. Verificare hash SHA256 pubblicati nelle release.
+1
View File
@@ -0,0 +1 @@
1.0.0
+679
View File
@@ -0,0 +1,679 @@
#!/usr/bin/env python3
"""
Build script for NewAdvSplash plugin - All configurations
Supports multiple build configurations with flexible parameters
"""
import argparse
import errno
import multiprocessing
import os
import shutil
import stat
import subprocess
import sys
import threading
import time
import xml.etree.ElementTree as ET
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path
from typing import List, Optional, Tuple
# Ensure stdout/stderr handle Unicode on Windows CI (cp1252 default breaks non-ASCII)
if sys.stdout.encoding and sys.stdout.encoding.lower() not in ('utf-8', 'utf_8'):
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
# ---------------------------------------------------------------------------
# Filesystem helpers
# ---------------------------------------------------------------------------
def _on_rmtree_error(func, path, exc_info):
if func in (os.unlink, os.rmdir) and exc_info[1].errno == errno.EACCES:
try:
os.chmod(path, stat.S_IWRITE)
func(path)
return
except Exception:
pass
for i in range(5):
try:
time.sleep(0.1 * (i + 1))
if os.path.isdir(path):
shutil.rmtree(path)
else:
os.unlink(path)
return
except Exception:
pass
raise exc_info[1]
def robust_rmtree(path):
if not os.path.exists(path):
return
try:
shutil.rmtree(path, onexc=_on_rmtree_error)
except TypeError:
try:
shutil.rmtree(path, onerror=_on_rmtree_error)
except Exception:
pass
except Exception:
try:
shutil.rmtree(path, ignore_errors=True)
except Exception:
pass
# ---------------------------------------------------------------------------
# Colors & Spinner
# ---------------------------------------------------------------------------
class Colors:
CYAN = "\033[36m"
GREEN = "\033[32m"
YELLOW = "\033[33m"
RED = "\033[31m"
GRAY = "\033[90m"
BLUE = "\033[34m"
RESET = "\033[0m"
BOLD = "\033[1m"
BRIGHT_GREEN = "\033[92m"
BRIGHT_CYAN = "\033[96m"
BRIGHT_WHITE = "\033[97m"
BRIGHT_YELLOW = "\033[93m"
BRIGHT_RED = "\033[91m"
class Spinner:
def __init__(self, message: str = "Building...", delay: float = 0.1, total: int = 0):
self.spinner = ['\u280b', '\u2819', '\u2839', '\u2838', '\u283c', '\u2834', '\u2826', '\u2827', '\u2807', '\u280f']
self.delay = delay
self.message = message
self.running = False
self.thread = None
self.start_time = time.time()
def update(self, current=None):
pass
def _spin(self):
idx = 0
_block = '\u28ff'
while self.running:
elapsed = time.time() - self.start_time
n_blocks = int(elapsed // 2)
time_blocks = f"{Colors.YELLOW}{_block * n_blocks}{Colors.RESET}"
spin_char = f"{Colors.YELLOW}{self.spinner[idx % len(self.spinner)]}{Colors.RESET}"
msg = f"{Colors.BOLD}{Colors.CYAN}{self.message}{Colors.RESET}"
time_str = f"{Colors.GREEN}{int(elapsed)}s{Colors.RESET}"
sys.stdout.write(f"\r{msg} {time_str} {time_blocks}{spin_char} ")
sys.stdout.flush()
idx += 1
time.sleep(self.delay)
sys.stdout.write("\r" + " " * (len(self.message) + 80) + "\r")
sys.stdout.flush()
def __enter__(self):
if sys.stdout.isatty():
self.running = True
self.thread = threading.Thread(target=self._spin, daemon=True)
self.thread.start()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if self.running:
self.running = False
if self.thread:
self.thread.join()
# ---------------------------------------------------------------------------
# Build configuration
# ---------------------------------------------------------------------------
class BuildConfig:
def __init__(self, name: str, config: str, platform: str, dest_dir: str):
self.name = name
self.config = config
self.platform = platform
self.dest_dir = dest_dir
CONFIGS = {
'x86-ansi': BuildConfig('x86-ansi', 'Release', 'Win32', 'x86-ansi'),
'x86-unicode': BuildConfig('x86-unicode', 'Release Unicode', 'Win32', 'x86-unicode'),
'x64-unicode': BuildConfig('x64-unicode', 'Release Unicode', 'x64', 'amd64-unicode'),
}
DLL_NAME = 'newadvsplash.dll'
_VSWHERE = Path(r'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe')
_VS_RANGES = {'2026': '[18.0,19.0)', '2022': '[17.0,18.0)'}
_VS_TOOLSETS = {'2026': 'v145', '2022': 'v143'}
# ---------------------------------------------------------------------------
# MSBuild discovery
# ---------------------------------------------------------------------------
def _find_msbuild_vswhere(vs_version: str) -> Optional[Tuple[Path, str, str]]:
if not _VSWHERE.exists():
return None
to_try = ['2026', '2022'] if vs_version == 'auto' else [vs_version]
for ver in to_try:
if ver not in _VS_RANGES:
continue
try:
result = subprocess.run(
[str(_VSWHERE), '-version', _VS_RANGES[ver], '-latest',
'-requires', 'Microsoft.Component.MSBuild',
'-find', r'MSBuild\**\Bin\MSBuild.exe'],
capture_output=True, text=True, timeout=15,
)
if result.returncode == 0:
lines = [ln.strip() for ln in result.stdout.splitlines() if ln.strip()]
if lines:
p = Path(lines[0])
if p.exists():
return p, _VS_TOOLSETS[ver], ver
except Exception:
pass
return None
def find_msbuild(vs_version: str = 'auto') -> Optional[Tuple[Path, str, str]]:
result = _find_msbuild_vswhere(vs_version)
if result:
return result
# Fallback: well-known paths
to_try = ['2026', '2022'] if vs_version == 'auto' else [vs_version]
for ver in to_try:
for edition in ('Community', 'Professional', 'Enterprise', 'BuildTools'):
p = Path(rf'C:\Program Files\Microsoft Visual Studio\{ver}\{edition}\MSBuild\Current\Bin\MSBuild.exe')
if p.exists():
return p, _VS_TOOLSETS[ver], ver
return None
# ---------------------------------------------------------------------------
# Project paths & version
# ---------------------------------------------------------------------------
def get_project_paths() -> Tuple[Path, Path, Path]:
script_dir = Path(__file__).parent.absolute()
project_dir = script_dir / 'src'
project_file = project_dir / 'NewAdvSplash.vcxproj'
dist_dir = script_dir / 'dist'
return project_dir, project_file, dist_dir
def get_plugins_dir() -> Optional[Path]:
"""Return workspace-level plugins/ dir (4 levels above src/modules/<plugin>/)."""
p = Path(__file__).parent.parent.parent.parent / 'plugins'
return p if p.is_dir() else None
def read_version() -> str:
vf = Path(__file__).parent / 'VERSION'
try:
return vf.read_text(encoding='utf-8-sig').strip()
except Exception:
return '0.0.0'
# ---------------------------------------------------------------------------
# CPU info & build optimizations
# ---------------------------------------------------------------------------
def get_cpu_info() -> dict:
try:
import psutil
logical = psutil.cpu_count(logical=True)
physical = psutil.cpu_count(logical=False)
return {'logical_cores': logical, 'physical_cores': physical,
'has_hyperthreading': logical > physical, 'has_psutil': True}
except ImportError:
n = multiprocessing.cpu_count()
return {'logical_cores': n, 'physical_cores': n,
'has_hyperthreading': False, 'has_psutil': False}
def get_optimal_threads() -> int:
info = get_cpu_info()
return info['physical_cores'] if info['has_hyperthreading'] and info['physical_cores'] > 1 else info['logical_cores']
def get_build_optimizations() -> List[str]:
return [
'/p:BuildInParallel=true',
'/p:MultiProcessorCompilation=true',
'/p:PreferredToolArchitecture=x64',
'/p:UseSharedCompilation=true',
'/nodeReuse:true',
'/p:GenerateResourceUsePreserializedResources=true',
]
def get_memory_optimizations() -> List[str]:
try:
import psutil
gb = psutil.virtual_memory().total / (1024 ** 3)
if gb >= 16:
return ['/p:DisableFastUpToDateCheck=false', '/p:BuildProjectReferences=true',
'/p:UseCommonOutputDirectory=false']
elif gb >= 8:
return ['/p:DisableFastUpToDateCheck=false']
return []
except ImportError:
return ['/p:DisableFastUpToDateCheck=false']
def print_cpu_info(use_parallel: bool, use_optimizations: bool = True) -> None:
if not use_parallel:
print(f"{Colors.CYAN}Build mode: {Colors.RESET} {Colors.BOLD}Single-threaded{Colors.RESET}")
if use_optimizations:
print(f"{Colors.CYAN}Optimizations: {Colors.RESET} {Colors.GREEN}ENABLED{Colors.RESET} {Colors.GRAY}(memory, caching){Colors.RESET}")
return
info = get_cpu_info()
optimal = get_optimal_threads()
print(f"{Colors.CYAN}Build mode: {Colors.RESET} {Colors.BRIGHT_WHITE}{'Parallel' if use_parallel else 'Sequential'}{Colors.RESET}")
print(f"{Colors.CYAN}Logical cores: {Colors.RESET} {Colors.BRIGHT_WHITE}{info['logical_cores']}{Colors.RESET}")
print(f"{Colors.CYAN}Physical cores: {Colors.RESET} {Colors.BRIGHT_WHITE}{info['physical_cores']}{Colors.RESET}")
if info['has_hyperthreading']:
print(f"{Colors.CYAN}Hyperthreading: {Colors.RESET} {Colors.BRIGHT_GREEN}ENABLED{Colors.RESET}")
print(f"{Colors.CYAN}Optimal threads: {Colors.RESET} {Colors.BRIGHT_WHITE}{optimal}{Colors.RESET} {Colors.GRAY}(using physical cores){Colors.RESET}")
else:
print(f"{Colors.CYAN}Hyperthreading: {Colors.RESET} {Colors.GRAY}NOT AVAILABLE{Colors.RESET}")
print(f"{Colors.CYAN}Optimal threads: {Colors.RESET} {Colors.BRIGHT_WHITE}{optimal}{Colors.RESET}")
print(f"{Colors.CYAN}MSBuild threads: {Colors.RESET} {Colors.BRIGHT_WHITE}{optimal}{Colors.RESET}")
if use_optimizations:
print(f"{Colors.CYAN}Optimizations: {Colors.RESET} {Colors.BRIGHT_GREEN}ENABLED{Colors.RESET} {Colors.GRAY}(parallel, memory, caching){Colors.RESET}")
try:
import psutil
gb = psutil.virtual_memory().total / (1024 ** 3)
print(f"{Colors.CYAN}Available memory: {Colors.RESET} {Colors.BRIGHT_WHITE}{gb:.1f} GB{Colors.RESET}")
except ImportError:
print(f"{Colors.CYAN}Available memory: {Colors.RESET} {Colors.GRAY}Unknown (install psutil){Colors.RESET}")
else:
print(f"{Colors.CYAN}Optimizations: {Colors.RESET} {Colors.BRIGHT_RED}DISABLED{Colors.RESET}")
if not info['has_psutil']:
print(f"{Colors.GRAY}Note: Install 'psutil' for detailed CPU/memory info (pip install psutil){Colors.RESET}")
print()
# ---------------------------------------------------------------------------
# Build helpers
# ---------------------------------------------------------------------------
def format_time(seconds: float) -> str:
if seconds < 60:
return f"{seconds:.2f}s"
elif seconds < 3600:
return f"{int(seconds // 60)}m {seconds % 60:.1f}s"
return f"{int(seconds // 3600)}h {int((seconds % 3600) // 60)}m {seconds % 60:.0f}s"
def build_configuration(
msbuild_path: Path,
project_file: Path,
config: BuildConfig,
platform_toolset: str,
*,
rebuild: bool = True,
verbosity: str = 'quiet',
parallel: bool = True,
optimizations: bool = True,
counter: str = "",
capture_output: bool = False,
) -> Tuple[bool, float, str]:
optimal = get_optimal_threads()
cmd = [
str(msbuild_path),
str(project_file),
f'/t:{"Rebuild" if rebuild else "Build"}',
f'/p:Configuration={config.config}',
f'/p:Platform={config.platform}',
f'/p:OutDir=Build\\{config.name}\\',
f'/p:IntDir=Build\\{config.name}\\obj\\',
'/p:WindowsTargetPlatformVersion=10.0',
f'/p:PlatformToolset={platform_toolset}',
f'/v:{verbosity}',
]
if parallel:
cmd += [f'/maxcpucount:{optimal}', '/p:UseMultiToolTask=true', f'/p:CL_MPCount={optimal}']
cmd += ['/p:Optimization=MaxSpeed', '/p:ExceptionHandling=Sync']
if optimizations:
cmd += get_build_optimizations() + get_memory_optimizations()
if not capture_output:
color = Colors.BRIGHT_YELLOW
print(f"\n{color}{'='*60}{Colors.RESET}")
label = f"[{counter}] " if counter else ""
print(f"{color}Building {Colors.BRIGHT_WHITE}{config.name:15s}{Colors.RESET} {color}{label}({'rebuild' if rebuild else 'incremental'}){Colors.RESET}")
print(f"{color}{'='*60}{Colors.RESET}")
start = time.time()
try:
if capture_output:
result = subprocess.run(cmd, check=False, capture_output=True, text=True)
return result.returncode == 0, time.time() - start, result.stdout + result.stderr
else:
result = subprocess.run(cmd, check=False)
return result.returncode == 0, time.time() - start, ""
except Exception as e:
elapsed = time.time() - start
msg = f"ERROR: Build failed with exception: {e}"
if capture_output:
return False, elapsed, msg
print(msg)
return False, elapsed, ""
def copy_output(project_dir: Path, dist_dir: Path, config: BuildConfig) -> Tuple[bool, int, Optional[Path]]:
output_file = project_dir / 'Build' / config.name / DLL_NAME
if not output_file.exists():
print(f"ERROR: DLL not found: {output_file}")
return False, 0, None
dest = dist_dir / config.dest_dir
dest.mkdir(parents=True, exist_ok=True)
try:
dst = dest / DLL_NAME
shutil.copy2(output_file, dst)
return True, output_file.stat().st_size, dst
except Exception as e:
print(f"ERROR: Failed to copy {config.name}: {e}")
return False, 0, None
def copy_to_plugins(dist_dir: Path, config: BuildConfig, plugins_dir: Path) -> Optional[Path]:
"""Copy DLL from dist/<dest_dir>/ to plugins/<dest_dir>/."""
src = dist_dir / config.dest_dir / DLL_NAME
if not src.exists():
return None
dst_dir = plugins_dir / config.dest_dir
dst_dir.mkdir(parents=True, exist_ok=True)
dst = dst_dir / DLL_NAME
shutil.copy2(src, dst)
return dst
def clean_build_artifacts(project_dir: Path, configs: List[BuildConfig]) -> None:
print(f"\n{Colors.CYAN}Cleaning build artifacts...{Colors.RESET}")
build_base = project_dir / 'Build'
if not build_base.exists():
return
for cfg in configs:
d = build_base / cfg.name
if d.exists():
try:
robust_rmtree(d)
print(f" {Colors.GRAY}- Cleaned:{Colors.RESET} {cfg.name}")
except Exception as e:
print(f" {Colors.RED}- Failed to clean {cfg.name}: {e}{Colors.RESET}")
try:
if build_base.exists() and not any(build_base.iterdir()):
build_base.rmdir()
except Exception:
pass
print(f"{Colors.BRIGHT_GREEN}Build artifacts cleaned successfully.{Colors.RESET}")
def print_available_configurations(project_file: Path) -> None:
try:
tree = ET.parse(project_file)
root = tree.getroot()
ns = {'ms': 'http://schemas.microsoft.com/developer/msbuild/2003'}
configs = []
for ig in root.findall('.//ms:ItemGroup', ns):
for pc in ig.findall('ms:ProjectConfiguration', ns):
inc = pc.get('Include', '')
parts = inc.split('|')
if len(parts) == 2:
configs.append(tuple(parts))
print("Available configurations in project:")
print("-" * 60)
from collections import defaultdict
grouped: dict = defaultdict(list)
for cfg, plat in configs:
grouped[cfg].append(plat)
for cfg_name in sorted(grouped):
print(f" {cfg_name:25s} - {', '.join(sorted(grouped[cfg_name]))}")
print(f"\nTotal: {len(configs)} configuration(s)\n")
except Exception as e:
print(f"Could not parse project file: {e}")
_print_lock = threading.Lock()
def _build_configs_parallel(
msbuild_path: Path,
project_file: Path,
configs: List[BuildConfig],
platform_toolset: str,
*,
rebuild: bool,
verbosity: str,
parallel: bool,
optimizations: bool,
project_dir: Path,
dist_dir: Path,
) -> list:
n = len(configs)
print(f"\nParallel: launching {n} builds simultaneously...")
print("=" * 50)
total_start = time.time()
results_by_idx: dict = {}
idx_lock = threading.Lock()
def _build_one(idx: int, config: BuildConfig):
import contextlib
import io as _io
success, build_time, captured = build_configuration(
msbuild_path, project_file, config, platform_toolset,
rebuild=rebuild, verbosity=verbosity,
parallel=parallel, optimizations=optimizations,
capture_output=True,
)
copy_buf = _io.StringIO()
if success:
with contextlib.redirect_stdout(copy_buf):
copy_ok, file_size, dest_path = copy_output(project_dir, dist_dir, config)
else:
copy_ok, file_size, dest_path = False, 0, None
with _print_lock:
sys.stdout.write("\r" + " " * 80 + "\r")
sys.stdout.flush()
tag = "OK" if (success and copy_ok) else "FAILED"
size_str = f"{file_size:,} bytes" if file_size > 0 else "N/A"
copy_out = copy_buf.getvalue()
if copy_out.strip():
print(copy_out.rstrip())
if captured.strip():
lines = [ln for ln in captured.splitlines() if "MSBuild" not in ln and "Copyright" not in ln]
filtered = "\n".join(lines).strip()
if filtered:
print(filtered)
color = Colors.BRIGHT_GREEN if (success and copy_ok) else Colors.RED
print(f"{color}[{tag}]{Colors.RESET} {config.name} ({format_time(build_time)}) {size_str}")
if dest_path:
print(f" -> {dest_path}")
with idx_lock:
results_by_idx[idx] = (config, success and copy_ok, build_time, file_size, dest_path)
with Spinner("Building configurations...", total=n) as s:
with ThreadPoolExecutor(max_workers=n) as executor:
futures = {executor.submit(_build_one, i, cfg): i for i, cfg in enumerate(configs)}
for fut in as_completed(futures):
s.update()
exc = fut.exception()
if exc:
idx = futures[fut]
with _print_lock:
print(f"ERROR: worker for config index {idx} raised: {exc}")
with idx_lock:
results_by_idx[idx] = (configs[idx], False, 0.0, 0, None)
wall = time.time() - total_start
print(f"\nAll {n} configs finished in {format_time(wall)} (wall clock)")
return [results_by_idx[i] for i in range(n)]
# ---------------------------------------------------------------------------
# main
# ---------------------------------------------------------------------------
def main() -> int:
parser = argparse.ArgumentParser(description='Build NewAdvSplash plugin for NSIS')
parser.add_argument('--configs', nargs='+',
choices=list(CONFIGS.keys()) + ['all'], default=None)
parser.add_argument('--config', # singular alias used by CI
choices=list(CONFIGS.keys()) + ['all'], default=None)
parser.add_argument('--rebuild', action='store_true', default=True)
parser.add_argument('--no-rebuild', action='store_false', dest='rebuild')
parser.add_argument('--parallel', action='store_true', default=True)
parser.add_argument('--no-parallel', action='store_false', dest='parallel')
parser.add_argument('--verbosity',
choices=['quiet', 'minimal', 'normal', 'detailed', 'diagnostic'],
default='quiet')
parser.add_argument('--clean', action='store_true', default=False)
parser.add_argument('--list', action='store_true')
parser.add_argument('--list-project', action='store_true')
parser.add_argument('--no-optimizations', action='store_true')
parser.add_argument('--vs-version', choices=['auto', '2026', '2022'], default='auto')
parser.add_argument('--final', action='store_true', default=False,
help='Force rebuild + clean (pre-release build)')
parser.add_argument('--install-dir', type=Path, default=None,
help='Copy built DLLs to this directory (in <config>/ subdirs)')
args = parser.parse_args()
# Merge --config (singular) into --configs list
if args.config and not args.configs:
args.configs = [args.config]
if args.final:
args.rebuild = True
args.clean = True
project_dir, project_file, dist_dir = get_project_paths()
if args.list_project:
print_available_configurations(project_file)
return 0
if args.list:
for name, config in CONFIGS.items():
print(f" {name:15s} -> {config.config} / {config.platform}")
return 0
if not project_file.exists():
print(f"ERROR: project file not found: {project_file}", file=sys.stderr)
return 3
msbuild_result = find_msbuild(args.vs_version)
if not msbuild_result:
print("ERROR: MSBuild not found. Install Visual Studio 2022 or 2026.", file=sys.stderr)
return 2
msbuild_path, platform_toolset, vs_version_name = msbuild_result
version = read_version()
if not args.configs:
configs_to_build = list(CONFIGS.values())
elif 'all' in args.configs:
configs_to_build = list(CONFIGS.values())
else:
configs_to_build = [CONFIGS[n] for n in args.configs]
# Banner
print(f"{Colors.BOLD}{Colors.BRIGHT_CYAN}{'='*60}")
print(f"Building NewAdvSplash plugin v{version} - {Colors.BRIGHT_WHITE}{len(configs_to_build)}{Colors.RESET} {Colors.BOLD}{Colors.BRIGHT_CYAN}configuration(s)")
print(f"{'='*60}{Colors.RESET}")
print(f"{Colors.CYAN}VS: {Colors.RESET} {Colors.BRIGHT_WHITE}{vs_version_name}{Colors.RESET} {Colors.GRAY}({platform_toolset}){Colors.RESET}")
print(f"{Colors.CYAN}MSBuild: {Colors.RESET} {Colors.BRIGHT_WHITE}{msbuild_path}{Colors.RESET}")
print(f"{Colors.CYAN}Project: {Colors.RESET} {Colors.BRIGHT_WHITE}{project_file}{Colors.RESET}")
print(f"{Colors.CYAN}Dist: {Colors.RESET} {Colors.BRIGHT_WHITE}{dist_dir}{Colors.RESET}")
print(f"{Colors.CYAN}Rebuild: {Colors.RESET} {Colors.BRIGHT_WHITE}{args.rebuild}{Colors.RESET}")
print(f"{Colors.CYAN}Verbosity: {Colors.RESET} {Colors.BRIGHT_WHITE}{args.verbosity}{Colors.RESET}")
print()
use_optimizations = not args.no_optimizations
print_cpu_info(args.parallel, use_optimizations)
build_results = []
total_start = time.time()
if args.parallel and len(configs_to_build) > 1:
build_results = _build_configs_parallel(
msbuild_path, project_file, configs_to_build, platform_toolset,
rebuild=args.rebuild, verbosity=args.verbosity,
parallel=True, optimizations=use_optimizations,
project_dir=project_dir, dist_dir=dist_dir,
)
else:
for i, config in enumerate(configs_to_build, 1):
success, b_time, _ = build_configuration(
msbuild_path, project_file, config, platform_toolset,
rebuild=args.rebuild, verbosity=args.verbosity,
parallel=args.parallel, optimizations=use_optimizations,
counter=f"{i}/{len(configs_to_build)}",
)
if success:
ok, size, path = copy_output(project_dir, dist_dir, config)
build_results.append((config, ok, b_time, size, path))
else:
build_results.append((config, False, b_time, 0, None))
total_time = time.time() - total_start
all_success = all(res[1] for res in build_results)
print(f"\n{Colors.BOLD}{Colors.BRIGHT_GREEN if all_success else Colors.RED}{'='*50}")
print("ALL BUILDS SUCCESSFUL!" if all_success else "SOME BUILDS FAILED!")
print(f"{'='*50}{Colors.RESET}")
# Copy to workspace plugins/ dir if present
plugins_dir = get_plugins_dir()
plugins_copied = []
if plugins_dir and all_success:
for cfg, ok, _, _, _ in build_results:
if ok:
dst = copy_to_plugins(dist_dir, cfg, plugins_dir)
if dst:
plugins_copied.append(str(dst))
if plugins_copied:
print(f"\n{Colors.CYAN}Installed to plugins/:{Colors.RESET}")
for p in plugins_copied:
print(f" {Colors.GRAY}->{Colors.RESET} {p}")
if args.install_dir and all_success:
print(f"\n{Colors.CYAN}Installing to {args.install_dir}...{Colors.RESET}")
for cfg, ok, _, _, path in build_results:
if ok and path:
dest = args.install_dir / cfg.dest_dir
dest.mkdir(parents=True, exist_ok=True)
shutil.copy2(path, dest / DLL_NAME)
print(f" {Colors.GRAY}- Installed:{Colors.RESET} {dest / DLL_NAME}")
print(f"\n{Colors.BOLD}{Colors.BRIGHT_CYAN}{'-'*50}")
print(f"Build Summary - VS {vs_version_name} ({platform_toolset}):")
for cfg, ok, b_time, size, _ in build_results:
color = Colors.GREEN if ok else Colors.RED
tag = "OK " if ok else "FAIL"
print(f" {color}{tag}{Colors.RESET} {cfg.name:15s} - {format_time(b_time):8s} - {size:11,d} bytes")
print(f"{Colors.BOLD}{Colors.BRIGHT_CYAN}{'-'*50}{Colors.RESET}")
print(f"Total time: {format_time(total_time)}\n")
if args.clean:
clean_build_artifacts(project_dir, configs_to_build)
return 0 if all_success else 1
if __name__ == '__main__':
sys.exit(main())
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
+177
View File
@@ -0,0 +1,177 @@
# Microsoft Developer Studio Project File - Name="advsplash" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=advsplash - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "advsplash.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "advsplash.mak" CFG="advsplash - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "advsplash - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "advsplash - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "advsplash - Win32 Release_Unicode" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "advsplash - Win32 Debug_Unicode" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "advsplash - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /Og /Os /Oy /I "..\ExDll" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /FD /c
# SUBTRACT CPP /Ox /Ow /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib vfw32.lib winmm.lib ole32.lib oleaut32.lib uuid.lib msvcrt.lib /nologo /entry:"DllMain" /subsystem:windows /dll /machine:I386 /nodefaultlib /out:"../../Plugins/newadvsplash.dll" /opt:nowin98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "advsplash - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\ExDll" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib vfw32.lib winmm.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"../../Plugins/newadvsplash.dll" /pdbtype:sept
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "advsplash - Win32 Release_Unicode"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release_Unicode"
# PROP BASE Intermediate_Dir "Release_Unicode"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_Unicode"
# PROP Intermediate_Dir "Release_Unicode"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_UNICODE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /Og /Os /Oy /I "..\ExDll" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_MBCS" /D "_USRDLL" /FD /c
# SUBTRACT CPP /Ox /Ow /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib vfw32.lib winmm.lib ole32.lib oleaut32.lib uuid.lib msvcrt.lib /nologo /entry:"DllMain" /subsystem:windows /dll /machine:I386 /nodefaultlib /out:"../../Unicode/plugins/newadvsplash.dll" /opt:nowin98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "advsplash - Win32 Debug_Unicode"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_UNICODE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\ExDll" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib vfw32.lib winmm.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"../../Unicode/plugins/newadvsplash.dll" /pdbtype:sept
# SUBTRACT LINK32 /pdb:none
!ENDIF
# Begin Target
# Name "advsplash - Win32 Release"
# Name "advsplash - Win32 Debug"
# Name "advsplash - Win32 Release_Unicode"
# Name "advsplash - Win32 Debug_Unicode"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\advsplash.cpp
# End Source File
# Begin Source File
SOURCE=.\gif.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\ExDLL\exdll.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project
+28
View File
@@ -0,0 +1,28 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "advsplash"=.\advsplash.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################
+69
View File
@@ -0,0 +1,69 @@
NewAdvSplash.dll - plug-in that lets you throw
up a splash screen in NSIS installers with
fading effects (win2k/xp) and transparency.
At the same time can play wav-mp3 sound file.
Usage:
1) newadvsplash::show [/NOUNLOAD] Delay FadeIn FadeOut KeyColor [/BANNER] [/PASSIVE] [/NOCANCEL] FileName
Delay - time (milliseconds) to show image
FadeIn - time to show the fadein scene
FadeOut - time to show the fadeout scene
KeyColor - color used for transparency, could be any RGB value
(for ex. R=255 G=100 B=16 -> KeyColor=0xFF6410),
use KeyColor=-1 if there is no transparent color at your image.
If KeyColor=-2 and image type is gif, plug-in attempts to extract
transparency color value from the file header. For gif images
transparency on the static background works even if KeyColor=-1.
/BANNER - returns control to installer immediatelly after plug-in
activation. Not depends on installer page - parent window NULL.
/NOCANCEL - disables 'exit on user click' default behaviour.
/PASSIVE - not forces splash window to foreground.
FileName - splash image filename (with extension!). Bmp, gif and jpg
image types are supported.
For example:
newadvsplash::show 3000 0 0 -2 "$PLUGINSDIR\catch.gif"
or
newadvsplash::show /NOUNLOAD 1000 600 400 0xFF6410 /BANNER "$TEMP\spltmp.bmp"
Use /NOUNLOAD with /BANNER key - this case plug-in not waits for
the end of 'show' and returns control to installer. If used in .onInit
function, /BANNER key requires 'ShowWindow $HWNDPARENT 2' in .onGUIInit
2) newadvsplash::stop [/WAIT | /FADEOUT]
Without options terminates banner.
With /WAIT option waits for the end.
With /FADEOUT option forces banner close with fade out effect ('Delay' -> 0).
3) newadvsplash::play /NOUNLOAD [/LOOP] FileName
FileName - sound filename to play (with extension, wav, mp3 ...).
Empty Filename string "" stops sound.
For example:
newadvsplash::play /NOUNLOAD /LOOP "$PLUGINSDIR\snd.mp3"
newadvsplash::show 2000 1000 500 -1 "$PLUGINSDIR\iamfat.jpg"
4) newadvsplash::hwnd /NOUNLOAD
Gets splash window handle.
For example:
newadvsplash::hwnd /NOUNLOAD
Pop $0 ; $0 is window handle now
Compatibility:
Basic - Win95 and later.
Fadein/fadeout - win2k/winxp.
Original code - Justin
Converted to a plugin DLL by Amir Szekely (kichik)
Fading and transparency by Nik Medved (brainsucker)
Gif and jpeg support, /BANNER and /CANCEL, mp3 support - Takhir Bedertdinov
+82
View File
@@ -0,0 +1,82 @@
{{PageAuthor|Takhir}}
== Links ==
Download:<br>
<attach>NewAdvSplash.zip</attach><br>
[http://forums.winamp.com/showthread.php?s=&threadid=197479 Forum thread]
== Description ==
NewAdvSplash.dll - startup image banner plug-in with fading effects (win2k/xp) and transparency. At the same time can play sound file. On the base of AdvSplash NSIS plug-in with following add-ons: allows background installer initialization (async-banner mode); plays mp3 files; gif, jpeg and some other OleLoadPicture() formats; "passive" mode - not forces spalsh window to foreground; can return splash HWND to work with other plug-ins (Marquee, AnimGif) in the async mode.
Compatibility: basic - Win95 and later, fadein/fadeout - win2k/winxp.
== Installing ==
Unzip and place the .dll file into the Plugins directory.
== Entry points and parameters (NSIS script) ==
newadvsplash::show [/NOUNLOAD] Delay FadeIn FadeOut KeyColor [/BANNER] [/PASSIVE] [/NOCANCEL] FileName
; Delay
: time (milliseconds) to show image
; FadeIn
: time to show the fadein scene
; FadeOut
: time to show the fadeout scene
; KeyColor
: color used for transparency, could be any RGB value (for ex. R=255 G=100 B=16 -> KeyColor=0xFF6410), use KeyColor=-1 if there is no transparent color at your image. If KeyColor=-2 and image type is gif, plug-in attempts to extract transparency color value from the file header. For gif images transparency on the static background works even if KeyColor=-1.
; /BANNER
: returns control to installer immediatelly after plug-in activation.
; /NOCANCEL
: disables 'exit on user click' default behaviour.
; /PASSIVE
: not forces spalsh window to foreground
; FileName
: splash image filename (with extension!). Bmp, gif and jpg image types supported.
newadvsplash::stop [/WAIT | /FADEOUT]
: For /BANNER mode only! Without options terminates banner.
: With /WAIT option waits for the end.
: With /FADEOUT option forces banner close with fade out effect ('Delay' -> 0).
newadvsplash::play /NOUNLOAD [/LOOP] FileName
; FileName
: sound filename to play (with extension, wav, mp3 ...). Empty Filename string "" stops playing ('show' end does this as well).
; /LOOP
: loops sound.
newadvsplash::hwnd
: Gets splash window handle (use Pop to take it from stack)
== Examples ==
'Modeless' logo with sound
<highlight-nsis>
newadvsplash::play /NOUNLOAD /LOOP "$PLUGINSDIR\snd.mp3"
newadvsplash::show /NOUNLOAD 2000 1000 500 -2 /BANNER "$PLUGINSDIR\logo.gif"
; add your initialization code here
newadvsplash::stop /WAIT
</highlight-nsis>
Simple logo
<highlight-nsis>
newadvsplash::show 2000 1000 500 -1 "$PLUGINSDIR\logo.jpg"
</highlight-nsis>
No return value.
[[Category:Plugins]]
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

+51
View File
@@ -0,0 +1,51 @@
;-----------------------------
; Requires AnimGif plug-in
Name "NewAdvSplash AnimBanner test"
OutFile "animbanner.exe"
!define IMG_NAME aist.gif
!include "MUI.nsh"
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE anb
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_INSTFILES
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE bna
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE "English"
Function anb
SetOutPath "$PLUGINSDIR"
File ${IMG_NAME}
newadvsplash::show /NOUNLOAD 2000 1000 500 -1 /BANNER "$PLUGINSDIR\${IMG_NAME}"
newadvsplash::hwnd /NOUNLOAD
Pop $0
AnimGif::play /NOUNLOAD /hwnd=$0 /bgcol=0xffffff "$PLUGINSDIR\${IMG_NAME}"
FunctionEnd
Function bna
newadvsplash::stop
AnimGif::stop
Delete "$PLUGINSDIR\${IMG_NAME}"
SetOutPath "$EXEDIR"
FunctionEnd
Section
newadvsplash::stop /wait
AnimGif::stop
Sleep 1000
newadvsplash::show /NOUNLOAD 2000 1000 500 -1 /BANNER "$PLUGINSDIR\${IMG_NAME}"
newadvsplash::hwnd /NOUNLOAD
Pop $0
AnimGif::play /NOUNLOAD /hwnd=$0 /bgcol=0xffffff "$PLUGINSDIR\${IMG_NAME}"
Sleep 1000
SectionEnd
+55
View File
@@ -0,0 +1,55 @@
;-----------------------------
; Requires AnimGif plug-in
Name "NewAdvSplash AnimSplash test"
OutFile "animsplash.exe"
!define IMG_NAME aist.gif
!include "MUI.nsh"
!define MUI_CUSTOMFUNCTION_GUIINIT begin
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_LANGUAGE "English"
Function .onInit
; following 2 lines can minimize all other desktop windows
; FindWindow $0 "Shell_TrayWnd"
; SendMessage $0 ${WM_COMMAND} 415 0
; the plugins dir is automatically deleted when the installer exits
InitPluginsDir
SetOutPath "$PLUGINSDIR"
; Modeless banner sample: show + wait
File "aist.gif"
newadvsplash::show /NOUNLOAD 2000 1000 500 -1 /BANNER "$PLUGINSDIR\${IMG_NAME}"
newadvsplash::hwnd /NOUNLOAD
Pop $0
AnimGif::play /NOUNLOAD /hwnd=$0 /bgcol=0xffffff "$PLUGINSDIR\${IMG_NAME}"
; you can add some background initialization code here (3.5 sec - aist.gif play time)
; wait & stop code also may be placed here, I moved them to .onGUIInit
; as a /BANNER (modeless) sample only.
FunctionEnd
Function begin
newadvsplash::stop /wait ; waits or exits immediately if 'show' already finished
AnimGif::stop
Delete "$PLUGINSDIR\${IMG_NAME}"
SetOutPath "$EXEDIR"
; plug-in requires this to be called in .onGUIInit in the BANNER mode only
ShowWindow $HWNDPARENT ${SW_RESTORE}
FunctionEnd
Section
SectionEnd
+43
View File
@@ -0,0 +1,43 @@
Name "NewAdvSplash BannerMUI test"
OutFile "bannermui.exe"
!include "MUI.nsh"
!define MUI_CUSTOMFUNCTION_GUIINIT MUIGUIInit
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_LANGUAGE "English"
!define IMG_NAME aist.gif
Function .onInit
; the plugins dir is automatically deleted when the installer exits
InitPluginsDir
SetOutPath "$PLUGINSDIR"
; Modeless banner sample: show + wait
File ${IMG_NAME}
newadvsplash::show /NOUNLOAD 2000 1000 500 -2 /BANNER "$PLUGINSDIR\${IMG_NAME}"
Sleep 2000 ; not changes 3.5 sec of 'show time'. add your code instead of sleep
FunctionEnd
; MUI requires custom function definition
Function MUIGUIInit
newadvsplash::stop /wait ; waits or exits immediately if finished, use just 'stop' to terminate
Delete "$PLUGINSDIR\${IMG_NAME}"
SetOutPath "$EXEDIR"
; plug-in requires this to be called in .onGUIInit
; if you use 'show' in the .onInit function with /BANNER key.
ShowWindow $HWNDPARENT ${SW_RESTORE}
FunctionEnd
Section
SectionEnd
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

+51
View File
@@ -0,0 +1,51 @@
Name "NewAdvSplash.dll test"
OutFile "newadvsplash.exe"
!define IMG_NAME1 splash.bmp
!define IMG_NAME2 aist.gif
!include WinMessages.nsh
Function .onInit
; the plugins dir is automatically deleted when the installer exits
InitPluginsDir
SetOutPath "$PLUGINSDIR"
; optional - mp3, use /LOOP key for 'non-stop'
# File "09.mp3"
# newadvsplash::play /NOUNLOAD "$PLUGINSDIR\09.mp3"
; Modal banner sample: show
File "/oname=$PLUGINSDIR\${IMG_NAME1}" "${NSISDIR}\Contrib\Graphics\Wizard\llama.bmp"
newadvsplash::show 1000 100 500 0x04025C /NOCANCEL "$PLUGINSDIR\${IMG_NAME1}"
Delete "$PLUGINSDIR\${IMG_NAME1}"
Sleep 500 ; optional
; Modeless banner sample: show + wait
File ${IMG_NAME2}
newadvsplash::show /NOUNLOAD 2000 1000 500 -2 /BANNER "$PLUGINSDIR\${IMG_NAME2}"
Sleep 2000 ; not changes 3.5 sec of 'show time'. add your code instead of sleep
FunctionEnd
; MUI requires custom function definition
Function .onGUIInit
newadvsplash::stop /wait ; waits or exits immediately if finished, remove /wait to terminate now
Delete "$PLUGINSDIR\${IMG_NAME2}"
SetOutPath "$EXEDIR"
; plug-in requires this to be called in .onGUIInit
; if you use 'show' in the .onInit function with /BANNER key.
ShowWindow $HWNDPARENT ${SW_RESTORE}
FunctionEnd
Section
SectionEnd
+34
View File
@@ -0,0 +1,34 @@
Name "NewAdvSplash.dll StopFade test"
OutFile "stopfade.exe"
!define IMG_NAME2 aist.gif
!include WinMessages.nsh
; MUI requires custom function definition
Function .onGUIInit
InitPluginsDir
SetOutPath "$PLUGINSDIR"
; Modeless banner with variable initialization time - up to 10 sec
; uses 'soft' stop() with fade out
File ${IMG_NAME2}
newadvsplash::show /NOUNLOAD 10000 1000 500 -2 /BANNER "$PLUGINSDIR\${IMG_NAME2}"
Sleep 2000 ; add here your initialization code (up to 11 sec) instead of sleep
newadvsplash::stop /fadeout
# newadvsplash::stop /wait
# newadvsplash::stop
Delete "$PLUGINSDIR\${IMG_NAME2}"
SetOutPath "$EXEDIR"
FunctionEnd
Section
SectionEnd
+38
View File
@@ -0,0 +1,38 @@
; Requires marquee plug-in
; Displays text on the splash window
!define IMG_NAME catch.ver.gif
Name "NewAdvSplash Version test"
OutFile "version.exe"
!include WinMessages.nsh
Function .onInit
InitPluginsDir
SetOutPath "$PLUGINSDIR"
File "${IMG_NAME}"
newadvsplash::show /NOUNLOAD 3000 1000 500 -2 /BANNER /NOCANCEL "$PLUGINSDIR\${IMG_NAME}"
newadvsplash::hwnd /NOUNLOAD
Pop $0
Sleep 100 ; to make window visible - this case you can skip /GCOL=00ff00 parameter
marquee::start /NOUNLOAD /left=73 /right=2 /COLOR=ff0000 /hwnd=$0 /step=0 /interval=100 /top=15 /height=35 /width=17 /start=right "v. 3.17"
FunctionEnd
Function .onGUIInit
newadvsplash::stop /wait
marquee::stop
Delete "$PLUGINSDIR\${IMG_NAME}"
SetOutPath "$EXEDIR" ; after this system can remove PLUGINSDIR
ShowWindow $HWNDPARENT ${SW_RESTORE}
FunctionEnd
Section
SectionEnd
+186
View File
@@ -0,0 +1,186 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release Unicode|Win32">
<Configuration>Release Unicode</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release Unicode|x64">
<Configuration>Release Unicode</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>NewAdvSplash</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'"
Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'"
Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets"
Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets"
Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>
WIN32;NDEBUG;_WINDOWS;_USRDLL;EXDLL_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<Optimization>MaxSpeed</Optimization>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>
kernel32.lib;user32.lib;gdi32.lib;ole32.lib;vfw32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>
WIN32;NDEBUG;_WINDOWS;_USRDLL;EXDLL_EXPORTS;UNICODE;_UNICODE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<Optimization>MaxSpeed</Optimization>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>
kernel32.lib;user32.lib;gdi32.lib;ole32.lib;vfw32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>
NDEBUG;_WINDOWS;_USRDLL;EXDLL_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<Optimization>MaxSpeed</Optimization>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>
kernel32.lib;user32.lib;gdi32.lib;ole32.lib;vfw32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>
NDEBUG;_WINDOWS;_USRDLL;EXDLL_EXPORTS;UNICODE;_UNICODE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<Optimization>MaxSpeed</Optimization>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>
kernel32.lib;user32.lib;gdi32.lib;ole32.lib;vfw32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="advsplash.cpp" />
<ClCompile Include="gif.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+539
View File
@@ -0,0 +1,539 @@
/***************************************************
* FILE NAME: advsplash.cpp
*
* Copyright 2003 - Present NSIS
*
* PURPOSE:
* Splash screen in NSIS installers with fading
* and transparency effects
*
* CHANGE HISTORY
*
* Author Date Modifications
*
* Justin Original
* Amir Szekely (kichik) Converted to a plugin DLL
* Nik Medved (brainsucker) Fading and transparency by
* Takhir Bedertdinov
* 10-26-2004 Gif and jpeg support
* 06-25-2005 modeless mode
* 08-30-2005 hwnd entry point for AnimGif
* 10-16-2005 "no transparency" bug for white bg images fixed
* 03-04-2006 /PASSIVE mode
* 04-04-2006 NULL parent HWND for /BANNER mode
* hbatista
* 04-05-2007 Unregister window on 'stop'
* Takhir
* 11-20-2007 "stop /fadeout" option - decreases sleep time
* "stop /wait" fully replaces ::wait call
**************************************************/
// For layered windows
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <tchar.h>
#include <windowsx.h>
#include <olectl.h>
#include <stdio.h>
#include <vfw.h>
#include "exdll.h"
#ifndef WS_EX_LAYERED
#define WS_EX_LAYERED 0x00080000
#define LWA_COLORKEY 0x00000001
#define LWA_ALPHA 0x00000002
#endif // ndef WS_EX_LAYERED
#define RESOLUTION 32 // 32 ms ~ 30 fps ;) (32? I like SHR more than iDIV ;)
#define MAX_SHOW_TIME 60000
enum FADE_STATES
{
FADE_IN,
FADE_SLEEP,
FADE_OUT
};
const TCHAR classname[4] = _T("_sp");
HWND myWnd = NULL;
HINSTANCE g_hInstance;
HANDLE hThread = NULL;
BITMAP bm;
HBITMAP g_hbm;
int resolution = RESOLUTION;
int sleep_val, fadein_val, fadeout_val, state, timeleft, keycolor, alphaparam;
LPPICTURE pIPicture = NULL;
bool modal = true, nocancel = false, setfg = true;
UINT timerEvent;
static WNDCLASS wc;
typedef BOOL(_stdcall *_tSetLayeredWindowAttributesProc)(HWND hwnd, // handle to the layered window
COLORREF crKey, // specifies the color key
BYTE bAlpha, // value for the blend function
DWORD dwFlags // action
);
_tSetLayeredWindowAttributesProc SetLayeredWindowAttributesProc;
int getTransparencyColor(TCHAR *fn_src);
void sf(HWND hw)
{
DWORD ctid = GetCurrentThreadId();
DWORD ftid = GetWindowThreadProcessId(GetForegroundWindow(), NULL);
AttachThreadInput(ftid, ctid, TRUE);
SetForegroundWindow(hw);
AttachThreadInput(ftid, ctid, FALSE);
}
/*****************************************************
* FUNCTION NAME: WndProc()
* PURPOSE:
* window proc.
* SPECIAL CONSIDERATIONS:
* for paint purposes mainly
*****************************************************/
static LRESULT CALLBACK WndProc(HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
PAINTSTRUCT ps;
RECT r;
long w, h;
switch (uMsg)
{
case WM_CREATE:
SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
SetWindowLong(hwnd, GWL_STYLE, 0);
SetWindowPos(hwnd, NULL,
r.left + (r.right - r.left - bm.bmWidth) / 2,
r.top + (r.bottom - r.top - bm.bmHeight) / 2,
bm.bmWidth, bm.bmHeight,
SWP_NOZORDER | SWP_SHOWWINDOW);
return 0;
case WM_PAINT:
BeginPaint(hwnd, &ps);
if (pIPicture != NULL)
{
GetClientRect(hwnd, &r);
pIPicture->get_Width(&w);
pIPicture->get_Height(&h);
pIPicture->Render(ps.hdc, r.left,
r.top, r.right - r.left, r.bottom - r.top, 0, h, w, -h, &r);
}
EndPaint(hwnd, &ps);
case WM_CLOSE:
return 0;
case WM_LBUTTONDOWN:
if (nocancel)
break;
case WM_TIMER:
timeKillEvent(timerEvent);
if (setfg)
sf(hwnd);
PlaySound(0, 0, 0);
DestroyWindow(hwnd);
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
/*****************************************************
* FUNCTION NAME: SetTransparentRegion()
* PURPOSE:
* creates window region
* SPECIAL CONSIDERATIONS:
* kind of skin creation from bmp
*****************************************************/
void SetTransparentRegion(HWND myWnd)
{
HDC dc;
int x, y;
HRGN region, cutrgn;
BITMAPINFO bmi = {{sizeof(BITMAPINFOHEADER), bm.bmWidth, bm.bmHeight, 1, 32, BI_RGB, 0, 0, 0, 0, 0}};
int size = bm.bmWidth * bm.bmHeight * 4;
int *pbmp = (int *)GlobalAlloc(GPTR, size),
*bmp;
bmp = pbmp;
dc = CreateCompatibleDC(NULL);
SelectObject(dc, g_hbm);
x = GetDIBits(dc, g_hbm, 0, bm.bmHeight, bmp, &bmi, DIB_RGB_COLORS);
region = CreateRectRgn(0, 0, bm.bmWidth, bm.bmHeight);
// Search for transparent pixels
for (y = bm.bmHeight - 1; y >= 0; y--)
for (x = 0; x < bm.bmWidth;)
if ((*bmp & 0xFFFFFF) == keycolor)
{
int j = x;
while ((x < bm.bmWidth) && ((*bmp & 0xFFFFFF) == keycolor))
bmp++, x++;
// Cut transparent pixels from the original region
cutrgn = CreateRectRgn(j, y, x, y + 1);
CombineRgn(region, region, cutrgn, RGN_XOR);
DeleteObject(cutrgn);
}
else
bmp++, x++;
// Set resulting region.
SetWindowRgn(myWnd, region, TRUE);
DeleteObject(region);
DeleteObject(dc);
GlobalFree(pbmp);
}
/*****************************************************
* FUNCTION NAME: TimeProc()
* PURPOSE:
* fade in/out tracking
* SPECIAL CONSIDERATIONS:
* works without WM_TIMER
*****************************************************/
void CALLBACK TimeProc(UINT uID,
UINT uMsg,
DWORD_PTR dwUser,
DWORD_PTR dw1,
DWORD_PTR dw2)
{
int call = -1;
switch (state)
{
case FADE_IN:
if (timeleft == 0)
{
timeleft = sleep_val;
state++;
if (SetLayeredWindowAttributesProc != NULL)
call = 255;
}
else
{
call = ((fadein_val - timeleft) * 255) / fadein_val;
break;
}
case FADE_SLEEP:
if (timeleft == 0)
{
timeleft = fadeout_val;
state++;
}
else
break;
case FADE_OUT:
if (timeleft == 0)
{
PostMessage((HWND)dwUser, WM_TIMER, 0, 0);
return;
}
else
{
call = ((timeleft) * 255) / fadeout_val;
break;
}
}
// Transparency value aquired, and could be set...
if ((call >= 0) && SetLayeredWindowAttributesProc != NULL)
SetLayeredWindowAttributesProc((HWND)dwUser, keycolor,
call,
alphaparam);
// Time is running out...
timeleft--;
}
/*****************************************************
* FUNCTION NAME: play()
* PURPOSE:
* PlaySound dll entry point
* SPECIAL CONSIDERATIONS:
* makes PlaySound working on Win98
* works with /NOUNLOAD parameter only
* wav files are huge :-(
* but not flushes on the screen like mci window does
* Use it BEFORE 'show' call
*****************************************************/
extern "C" void __declspec(dllexport) play(HWND hwndParent,
int string_size,
TCHAR *variables,
stack_t **stacktop)
{
TCHAR fn[MAX_PATH];
DWORD snd = SND_FILENAME | SND_ASYNC | SND_NODEFAULT;
EXDLL_INIT();
if (popstring(fn) == 0)
{
if (lstrcmpi(fn, _T("/loop")) == 0)
{
snd |= SND_LOOP;
*fn = 0;
popstring(fn);
}
if (*fn == 0)
{
PlaySound(NULL, NULL, 0);
}
else
{
PlaySound(fn, NULL, snd);
}
}
}
/*****************************************************
* FUNCTION NAME: splashThread()
* PURPOSE:
* modal/modeless banner presentation
* SPECIAL CONSIDERATIONS:
* from CreateThread runs window "detached", with NULL
* parent, otherwise uses current page as parent
*****************************************************/
DWORD WINAPI splashThread(LPVOID lpParameter)
{
MSG msg;
HWND hParent = (HWND)lpParameter;
wc.lpfnWndProc = WndProc;
wc.hInstance = g_hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = classname;
if (RegisterClass(&wc))
{
pIPicture->get_Handle((OLE_HANDLE *)&g_hbm);
GetObject((HGDIOBJ)g_hbm, sizeof(BITMAP), &bm);
myWnd = CreateWindowEx(WS_EX_TOOLWINDOW | (setfg ? WS_EX_TOPMOST : 0) |
(SetLayeredWindowAttributesProc != NULL ? WS_EX_LAYERED : 0),
classname, classname, 0, 0, 0, 0, 0,
hParent, NULL, g_hInstance, NULL);
// Set transparency / key color
if (SetLayeredWindowAttributesProc != NULL)
SetLayeredWindowAttributesProc(myWnd, keycolor,
fadein_val > 0 ? 0 : 255,
alphaparam);
if (keycolor != -1)
SetTransparentRegion(myWnd);
// Start up timer...
state = FADE_IN;
timeleft = fadein_val;
timerEvent = timeSetEvent(resolution, RESOLUTION / 4, TimeProc,
(DWORD_PTR)myWnd, TIME_PERIODIC);
while (IsWindow(myWnd) && GetMessage(&msg, myWnd, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
pIPicture->Release();
pIPicture = NULL; // do not re-use with /NOUNLOAD
}
myWnd = NULL;
// Stop currently playing wave, we want to exit
PlaySound(0, 0, 0);
return 0;
}
/*****************************************************
* FUNCTION NAME: show()
* PURPOSE:
* image banner "show" dll entry point
* SPECIAL CONSIDERATIONS:
*
*****************************************************/
extern "C" void __declspec(dllexport) show(HWND hwndParent,
int string_size,
TCHAR *variables,
stack_t **stacktop)
{
DEVMODE dm;
TCHAR fn[MAX_PATH];
WCHAR wcPort[MAX_PATH];
DWORD dwThreadId;
DWORD dwMainThreadId = GetCurrentThreadId();
EXDLL_INIT();
// 3 fade parameters and keycolor from stack come first
popstring(fn);
sleep_val = _tcstol(fn, NULL, 0);
popstring(fn);
fadein_val = _tcstol(fn, NULL, 0);
popstring(fn);
fadeout_val = _tcstol(fn, NULL, 0);
popstring(fn);
keycolor = _tcstol(fn, NULL, 0);
// other parameters (if any) + filename
while (!popstring(fn) && fn[0] == _T('/'))
{
if (lstrcmpi(fn, _T("/nocancel")) == 0)
nocancel = true;
else if (lstrcmpi(fn, _T("/passive")) == 0)
setfg = false;
else
modal = false;
}
if (keycolor == -2)
keycolor = getTransparencyColor(fn);
// Check for winXP/2k at 32 bpp transparency support
dm.dmSize = sizeof(DEVMODE);
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
if (dm.dmBitsPerPel >= 32)
{
HANDLE user32 = GetModuleHandle(_T("user32"));
SetLayeredWindowAttributesProc = (_tSetLayeredWindowAttributesProc)
GetProcAddress((HINSTANCE)user32, "SetLayeredWindowAttributes");
}
if (SetLayeredWindowAttributesProc == NULL)
{
// Fading+transparency is unsupported at old windows versions...
resolution = (sleep_val + fadein_val + fadeout_val) / 2;
fadeout_val = fadein_val = 0;
sleep_val = 1;
}
else
{
// div them by resolution - now times are in 32 ms "frames"
sleep_val >>= 5;
fadein_val >>= 5;
fadeout_val >>= 5;
// MS RGB - BGR format
alphaparam = LWA_ALPHA | (keycolor == -1 ? 0 : LWA_COLORKEY);
if (keycolor != -1)
keycolor = ((keycolor & 0xFF) << 16) + (keycolor & 0xFF00) +
((keycolor & 0xFF0000) >> 16);
}
// who wrote this script :-))
#ifdef _UNICODE
lstrcpy(wcPort, fn);
#else
MultiByteToWideChar(CP_ACP, 0, fn, -1, wcPort, sizeof(wcPort) / 2);
#endif
OleLoadPicturePath((LPOLESTR)wcPort, 0, 0, 0, IID_IPicture, (void **)&pIPicture);
if (pIPicture == NULL ||
(sleep_val + fadein_val + fadeout_val) <= 0)
return;
if (modal)
{
splashThread((void *)hwndParent);
// We should UnRegister class, since Windows NT series never does this by itself
UnregisterClass(wc.lpszClassName, g_hInstance);
}
else
{
// start thread and wait for window initialization
hThread = CreateThread(0, 0, splashThread, NULL, 0, &dwThreadId);
while (myWnd == NULL || !IsWindowVisible(myWnd))
Sleep(10);
if (setfg)
sf(myWnd);
}
}
/*****************************************************
* FUNCTION NAME: stop()
* PURPOSE:
* image banner "stop" dll entry point
* SPECIAL CONSIDERATIONS:
*
*****************************************************/
extern "C" void __declspec(dllexport) stop(HWND hwndParent,
int string_size,
TCHAR *variables,
stack_t **stacktop)
{
TCHAR cmd[64];
if (!modal && hThread != NULL)
{
if (popstring(cmd) == 0)
{
if (lstrcmpi(cmd, _T("/fadeout")) == 0)
{
if (SetLayeredWindowAttributesProc == NULL)
stop(hwndParent, string_size, variables, stacktop);
else
{
if (state == FADE_IN)
{
sleep_val = 1; // minimize sleep step - 1 frame only
}
else if (state == FADE_SLEEP)
{
timeleft = 1; // force sleep to finish
}
WaitForSingleObject(hThread, (fadein_val + fadeout_val + 3) * resolution);
}
}
if (lstrcmpi(cmd, _T("/wait")) == 0)
{
WaitForSingleObject(hThread,
resolution * (SetLayeredWindowAttributesProc == NULL ? 2 : fadein_val + fadeout_val + sleep_val + 3));
}
else
pushstring(cmd); // this is not our string
}
if (IsWindow(myWnd))
{
SendMessage(myWnd, WM_TIMER, 0, 0); // stops sound and destroys window
}
WaitForSingleObject(hThread, 1000);
CloseHandle(hThread);
hThread = NULL;
// hbatista
UnregisterClass(wc.lpszClassName, g_hInstance);
Sleep(10);
if (setfg)
sf(hwndParent);
}
}
/*****************************************************
* FUNCTION NAME: hwnd()
* PURPOSE:
* retrieves target window handle
* SPECIAL CONSIDERATIONS:
*
*****************************************************/
extern "C" void __declspec(dllexport) hwnd(HWND hwndParent,
int string_size,
TCHAR *variables,
stack_t **stacktop)
{
TCHAR s[16] = _T("");
if (IsWindow(myWnd))
wsprintf(s, _T("%d"), myWnd);
pushstring(s);
}
/*****************************************************
* FUNCTION NAME: DllMain()
* PURPOSE:
* Dll main (initialization) entry point
* SPECIAL CONSIDERATIONS:
*
*****************************************************/
BOOL WINAPI DllMain(HANDLE hInst,
ULONG ul_reason_for_call,
LPVOID lpReserved)
{
g_hInstance = (HINSTANCE)hInst;
return TRUE;
}
+99
View File
@@ -0,0 +1,99 @@
#ifndef _EXDLL_H_
#define _EXDLL_H_
#include <windows.h>
// only include this file from one place in your DLL.
// (it is all static, if you use it in two places it will fail)
#define EXDLL_INIT() \
{ \
g_stringsize = string_size; \
g_stacktop = stacktop; \
g_variables = variables; \
}
// For page showing plug-ins
#define WM_NOTIFY_OUTER_NEXT (WM_USER + 0x8)
#define WM_NOTIFY_CUSTOM_READY (WM_USER + 0xd)
#define NOTIFY_BYE_BYE 'x'
typedef struct _stack_t
{
struct _stack_t *next;
TCHAR text[1]; // this should be the length of string_size
} stack_t;
static unsigned int g_stringsize;
static stack_t **g_stacktop;
static TCHAR *g_variables;
enum
{
INST_0, // $0
INST_1, // $1
INST_2, // $2
INST_3, // $3
INST_4, // $4
INST_5, // $5
INST_6, // $6
INST_7, // $7
INST_8, // $8
INST_9, // $9
INST_R0, // $R0
INST_R1, // $R1
INST_R2, // $R2
INST_R3, // $R3
INST_R4, // $R4
INST_R5, // $R5
INST_R6, // $R6
INST_R7, // $R7
INST_R8, // $R8
INST_R9, // $R9
INST_CMDLINE, // $CMDLINE
INST_INSTDIR, // $INSTDIR
INST_OUTDIR, // $OUTDIR
INST_EXEDIR, // $EXEDIR
INST_LANG, // $LANGUAGE
__INST_LAST
};
// utility functions (not required but often useful)
static int __stdcall popstring(TCHAR *str)
{
stack_t *th;
if (!g_stacktop || !*g_stacktop)
return 1;
th = (*g_stacktop);
lstrcpy(str, th->text);
*g_stacktop = th->next;
GlobalFree((HGLOBAL)th);
return 0;
}
static void __stdcall pushstring(const TCHAR *str)
{
stack_t *th;
if (!g_stacktop)
return;
th = (stack_t *)GlobalAlloc(GPTR, sizeof(stack_t) + g_stringsize * sizeof(TCHAR));
lstrcpyn(th->text, str, g_stringsize);
th->next = *g_stacktop;
*g_stacktop = th;
}
static TCHAR *__stdcall getuservariable(int varnum)
{
if (varnum < 0 || varnum >= __INST_LAST)
return NULL;
return g_variables + varnum * g_stringsize;
}
static void __stdcall setuservariable(int varnum, const TCHAR *var)
{
if (varnum < 0 || varnum >= __INST_LAST)
return;
lstrcpy(g_variables + varnum * g_stringsize, var);
}
#endif //_EXDLL_H_
+257
View File
@@ -0,0 +1,257 @@
#include <windows.h>
#include <tchar.h>
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
// My gratitute to Andy Key. His GBM lib served as a base
// for this short gif decoder. I only added extraction
// of transparansy color and comments.
// Takhir
#define byte unsigned char
#define word unsigned short
#define make_word(a,b) (((word)a) + (((word)b) << 8))
typedef int GBM_ERR;
#define GBM_ERR_GIF_BPP ((GBM_ERR) 1100)
#define GBM_ERR_GIF_TERM ((GBM_ERR) 1101)
#define GBM_ERR_GIF_CODE_SIZE ((GBM_ERR) 1102)
#define GBM_ERR_GIF_CORRUPT ((GBM_ERR) 1103)
#define GBM_ERR_GIF_HEADER ((GBM_ERR) 1104)
#define GBM_ERR_OK ((GBM_ERR) 0)
#define GBM_ERR_BAD_MAGIC ((GBM_ERR) 5)
#define GBM_ERR_READ ((GBM_ERR) 7)
#define GBM_ERR_WRITE ((GBM_ERR) 8)
typedef unsigned int cword;
typedef struct
{
BOOLEAN ilace, errok;
int bpp;
byte pal[0x100*3];
} GIF_PRIV;
typedef struct
{
int fd; /* File descriptor to read */
int inx, size; /* Index and size in bits */
byte buf[255+3]; /* Buffer holding bits */
int code_size; /* Number of bits to return at once */
cword read_mask; /* 2^code_size-1 */
} READ_CONTEXT;
typedef struct
{
int x, y, w, h, bpp, pass;
BOOLEAN ilace;
int stride;
byte *data, *data_this_line;
} OUTPUT_CONTEXT;
typedef unsigned int cword;
typedef struct { byte r, g, b; } GBMRGB;
#define PRIV_SIZE 2000
typedef struct
{
int w, h, bpp; /* Bitmap dimensions */
byte priv[PRIV_SIZE]; /* Private internal buffer */
int trc;
char *szUrl;
} GBM;
/*...sgif_rhdr:0:*/
GBM_ERR gif_rhdr(int fd, GBM *gbm)
{
GIF_PRIV *gif_priv = (GIF_PRIV *) gbm->priv;
byte signiture[6], scn_desc[7], image_desc[10];
int img = -1, img_want = 0;
int bits_gct;
/* Read and validate signiture block */
if ( _read(fd, signiture, 6) != 6 )
return GBM_ERR_READ;
if ( memcmp(signiture, "GIF87a", 6) &&
memcmp(signiture, "GIF89a", 6) )
return GBM_ERR_BAD_MAGIC;
/* Read screen descriptor */
if ( _read(fd, scn_desc, 7) != 7 )
return GBM_ERR_READ;
bits_gct = gif_priv->bpp = (scn_desc[4] & 7) + 1;
// bits_gct = ((scn_desc[4] & 0x70) >> 4) + 1;
if ( scn_desc[4] & 0x80 )
/* Global colour table follows screen descriptor */
{
if ( _read(fd, gif_priv->pal, 3 << bits_gct) != (3 << bits_gct) )
return GBM_ERR_READ;
}
else
/* Blank out palette, but make entry 1 white */
{
memset(gif_priv->pal, 0, 3 << bits_gct);
gif_priv->pal[3] =
gif_priv->pal[4] =
gif_priv->pal[5] = 0xff;
}
/* Expected image descriptors / extension blocks / terminator */
while ( img < img_want )
{
if ( _read(fd, image_desc, 1) != 1 )
return GBM_ERR_READ;
switch ( image_desc[0] )
{
/*...s0x2c \45\ image descriptor:24:*/
case 0x2c:
if ( _read(fd, image_desc + 1, 9) != 9 )
return GBM_ERR_READ;
gbm->w = make_word(image_desc[5], image_desc[6]);
gbm->h = make_word(image_desc[7], image_desc[8]);
gif_priv->ilace = ( (image_desc[9] & 0x40) != 0 );
if ( image_desc[9] & 0x80 )
/* Local colour table follows */
{
gif_priv->bpp = (image_desc[9] & 7) + 1;
if ( _read(fd, gif_priv->pal, 3 << gif_priv->bpp) != (3 << gif_priv->bpp) )
return GBM_ERR_READ;
}
if ( ++img != img_want )
/* Skip the image data */
{
byte code_size, block_size;
if ( _read(fd, &code_size, 1) != 1 )
return GBM_ERR_READ;
do
{
if ( _read(fd, &block_size, 1) != 1 )
return GBM_ERR_READ;
_lseek(fd, block_size, SEEK_CUR);
}
while ( block_size );
}
break;
/*...e*/
/*...s0x21 \45\ extension block:24:*/
/* Ignore all extension blocks */
case 0x21:
{
/* Graphics and Comment ControlExtensions added by Takhir */
byte func_code, byte_count, rslt;
if ( _read(fd, &func_code, 1) != 1 )
return GBM_ERR_READ;
_read(fd, &byte_count, 1);
switch (func_code)
{
case 0xF9: // GraphicsControlExtensions
byte_count++;
for(;byte_count>0;byte_count--)
{
if ( _read(fd, &rslt, 1) != 1 )
return GBM_ERR_READ;
if((byte_count==5)&&(rslt&1)) gbm->trc=1;
if((byte_count==2)&&(gbm->trc==1))
gbm->trc=rslt;
}
break;
case 0xFE: // CommentControlExtensions
if(gbm->szUrl==NULL)
_lseek(fd, byte_count+1, SEEK_CUR);
else
{
gbm->szUrl[0] = 0;
if (_read(fd, gbm->szUrl, byte_count+1) != ((int)byte_count+1) )
return GBM_ERR_READ;
}
break;
default: // Other Extensions
do
{ _lseek(fd, byte_count, SEEK_CUR);
if ( _read(fd, &byte_count, 1) != 1 )
return GBM_ERR_READ;
}
while ( byte_count );
}
/* end of changes */
}
break;
/*...e*/
/*...s0x3b \45\ terminator:24:*/
/* Oi, we were hoping to get an image descriptor! */
case 0x3b:
return GBM_ERR_GIF_TERM;
/*...e*/
/*...sdefault:24:*/
default:
return GBM_ERR_GIF_HEADER;
/*...e*/
}
}
switch ( gif_priv->bpp )
{
case 1: gbm->bpp = 1; break;
case 2:
case 3:
case 4: gbm->bpp = 4; break;
case 5:
case 6:
case 7:
case 8: gbm->bpp = 8; break;
default: return GBM_ERR_GIF_BPP;
}
return GBM_ERR_OK;
}
/*...e*/
/*...sgif_rdata:0:*/
/*...sread context:0:*/
int getTransparencyColor(TCHAR* fn_src)
{
int fd;
GBM gbm;
GBMRGB *gbmrgb = (GBMRGB*)(gbm.priv + 8);
if(lstrcmpi(fn_src + lstrlen(fn_src) - 4, _T(".gif")) != 0) return -1;
gbm.trc = -1;
gbm.szUrl = NULL;
if ((fd = _topen(fn_src, O_RDONLY | O_BINARY))==-1) return 0;
gif_rhdr( fd, &gbm);
_close(fd);
if(gbm.trc == -1 || gbm.trc > 255) return -1;
fd = 0;
memcpy(&fd, &gbmrgb[gbm.trc], 3);
/*char b[64];
wsprintf(b, "Index %d, color=0x%06x", gbm.trc, fd);
MessageBox(NULL, b, "Index & color", 0);*/
return fd;
}