switch to microsoft windows crate

This commit is contained in:
allenbenz
2021-02-15 23:57:27 -08:00
parent 4d66e12e89
commit b24853dfb7
9 changed files with 131 additions and 119 deletions

View File

@@ -1 +1,2 @@
error_on_unformatted = false
imports_layout = "Vertical"

17
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,17 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${file}"
}
]
}

29
.vscode/tasks.json vendored
View File

@@ -1,29 +0,0 @@
{
"version": "0.1.0",
"command": "cargo",
"isShellCommand": true,
"showOutput": "always",
"suppressTaskName": true,
"tasks": [
{
"taskName": "cargo build",
"args": [
"build"
],
"isBuildCommand": true
},
{
"taskName": "cargo run",
"args": [
"run"
]
},
{
"taskName": "cargo test",
"args": [
"test"
],
"isTestCommand": true
}
]
}

View File

@@ -1,6 +1,6 @@
[package]
name = "winrt-notification"
version = "0.2.3"
version = "0.3.0"
authors = ["allenbenz"]
keywords = ["notification", "windows", "toast", "notify"]
readme = "README.md"
@@ -8,19 +8,16 @@ description = "An incomplete wrapper over the WinRT toast api"
documentation = "https://allenbenz.github.io/winrt-notification/0_1_3/winrt_notification/"
repository = "https://github.com/allenbenz/winrt-notification"
license = "MIT"
exclude = [
".vscode/*"
]
exclude = [".vscode/*"]
edition = '2018'
[package.metadata.docs.rs]
default-target = "x86_64-pc-windows-msvc"
[dependencies.winrt]
version = "0.4.0"
features = ["windows-data", "windows-ui"]
[dependencies]
xml-rs = "0.6.1"
winapi = "^0.3.4"
strum = "0.8.0"
strum_macros = "0.8.0"
xml-rs = "0.8.3"
strum = { version = "0.20", features = ["derive"] }
windows = "0.3.1"
[build-dependencies]
windows = "0.3.1"

10
build.rs Normal file
View File

@@ -0,0 +1,10 @@
// see https://microsoft.github.io/windows-docs-rs/doc/bindings/windows/ for possible bindings
fn main() {
windows::build!(
windows::win32::system_services::NTSTATUS,
windows::win32::windows_programming::OSVERSIONINFOEXA,
windows::win32::windows_programming::OSVERSIONINFOEXW,
windows::data::xml::dom::XmlDocument,
windows::ui::notifications::{ToastNotification, ToastNotificationManager},
);
}

View File

@@ -1,6 +1,9 @@
extern crate winrt_notification;
use std::path::Path;
use winrt_notification::{IconCrop, Toast};
use winrt_notification::{
IconCrop,
Toast,
};
fn main() {
Toast::new("application that needs a toast with an image")

View File

@@ -1,5 +1,9 @@
extern crate winrt_notification;
use winrt_notification::{Duration, Sound, Toast};
use winrt_notification::{
Duration,
Sound,
Toast,
};
fn main() {
Toast::new(Toast::POWERSHELL_APP_ID)

View File

@@ -26,18 +26,23 @@
/// for Windows 7 and older support look into Shell_NotifyIcon
/// https://msdn.microsoft.com/en-us/library/windows/desktop/ee330740(v=vs.85).aspx
/// https://softwareengineering.stackexchange.com/questions/222339/using-the-system-tray-notification-area-app-in-windows-7
extern crate winapi;
extern crate winrt;
extern crate windows;
extern crate xml;
extern crate strum;
#[macro_use]
extern crate strum_macros;
extern crate strum;
use winrt::{FastHString, RuntimeContext};
use winrt::windows::data::xml::dom::IXmlDocumentIO;
use winrt::windows::ui::notifications::{ToastNotification, ToastNotificationManager};
use winrt::windows::ui::notifications::ToastTemplateType;
#[allow(dead_code)]
mod bindings {
::windows::include_bindings!();
}
use bindings::{
windows::data::xml::dom::XmlDocument,
windows::ui::notifications::ToastNotification,
windows::ui::notifications::ToastNotificationManager,
windows::HString,
};
use std::fmt;
use std::path::Path;
@@ -45,7 +50,7 @@ use std::path::Path;
use xml::escape::escape_str_attribute;
mod windows_check;
pub use winrt::Error;
pub use windows::Error;
pub struct Toast {
duration: String,
@@ -73,10 +78,10 @@ pub enum Sound {
Reminder,
SMS,
/// Play the loopable sound only once
#[strum(disabled = "true")]
#[strum(disabled)]
Single(LoopableSound),
/// Loop the loopable sound for the entire duration of the toast
#[strum(disabled = "true")]
#[strum(disabled)]
Loop(LoopableSound),
}
@@ -185,7 +190,8 @@ impl Toast {
self.duration = match duration {
Duration::Long => "duration=\"long\"",
Duration::Short => "duration=\"short\"",
}.to_owned();
}
.to_owned();
self
}
@@ -272,68 +278,57 @@ impl Toast {
}
/// Display the toast on the screen
pub fn show(&self) -> Result<(), winrt::Error> {
let _rt = RuntimeContext::init();
pub fn show(&self) -> windows::Result<()> {
//using this to get an instance of XmlDocument
let toast_xml =
ToastNotificationManager::get_template_content(ToastTemplateType::ToastText01).unwrap();
let toast_xml = XmlDocument::new()?;
//XmlDocument implements IXmlDocumentIO so this is safe
let toast_xml_as_xml_io = toast_xml.query_interface::<IXmlDocumentIO>().unwrap();
unsafe {
let template_binding = if windows_check::is_newer_than_windows81() {
"ToastGeneric"
} else
//win8 or win81
{
// Need to do this or an empty placeholder will be shown if no image is set
if self.images == "" {
"ToastText04"
} else {
"ToastImageAndText04"
}
};
(*toast_xml_as_xml_io).load_xml(&FastHString::new(&format!(
"<toast {}>
<visual>
<binding template=\"{}\">
{}
{}{}{}
</binding>
</visual>
{}
</toast>",
self.duration,
template_binding,
self.images,
self.title,
self.line1,
self.line2,
self.audio,
)))?
let template_binding = if windows_check::is_newer_than_windows81() {
"ToastGeneric"
} else
//win8 or win81
{
// Need to do this or an empty placeholder will be shown if no image is set
if self.images == "" {
"ToastText04"
} else {
"ToastImageAndText04"
}
};
toast_xml.load_xml(HString::from(format!(
"<toast {}>
<visual>
<binding template=\"{}\">
{}
{}{}{}
</binding>
</visual>
{}
</toast>",
self.duration,
template_binding,
self.images,
self.title,
self.line1,
self.line2,
self.audio,
)))?;
// Create the toast and attach event listeners
let toast_template = ToastNotification::create_toast_notification(&*toast_xml)?;
let toast_template = ToastNotification::create_toast_notification(toast_xml)?;
// Show the toast.
unsafe {
let toast_notifier = ToastNotificationManager::create_toast_notifier_with_id(
&FastHString::new(&self.app_id),
)?;
let result = toast_notifier.show(&*toast_template);
std::thread::sleep(std::time::Duration::from_millis(10));
result
}
let toast_notifier =
ToastNotificationManager::create_toast_notifier_with_id(HString::from(&self.app_id))?;
let result = toast_notifier.show(&toast_template);
std::thread::sleep(std::time::Duration::from_millis(10));
result
}
}
#[cfg(test)]
mod tests {
use ::*;
use crate::*;
use std::path::Path;
#[test]
@@ -360,4 +355,17 @@ mod tests {
// silently consume errors
.expect("notification failed");
}
#[test]
fn text_toast() {
Toast::new(Toast::POWERSHELL_APP_ID)
.title("just text in this toast")
.text1("line1")
.text2("line2")
.duration(Duration::Short)
.sound(Some(Sound::SMS))
.show()
// silently consume errors
.expect("notification failed");
}
}

View File

@@ -1,19 +1,21 @@
// Lifted from mattmccarty's work in os_info
use std::mem::zeroed;
use std::mem::size_of;
use winapi::shared::ntdef::NTSTATUS;
use winapi::shared::minwindef::DWORD;
use winapi::shared::ntstatus::STATUS_SUCCESS;
#[allow(dead_code)]
mod bindings {
::windows::include_bindings!();
}
use bindings::{
windows::win32::system_services::NTSTATUS,
windows::win32::windows_programming::*,
};
#[cfg(target_arch = "x86")]
use winapi::um::winnt::OSVERSIONINFOEXA;
#[cfg(not(target_arch = "x86"))]
use winapi::um::winnt::OSVERSIONINFOEXW;
use OSVERSIONINFOEXA;
#[cfg(target_arch = "x86")]
type OSVERSIONINFOEX = OSVERSIONINFOEXA;
#[cfg(not(target_arch = "x86"))]
use OSVERSIONINFOEXW;
#[cfg(not(target_arch = "x86"))]
type OSVERSIONINFOEX = OSVERSIONINFOEXW;
@@ -25,11 +27,10 @@ extern "system" {
pub fn is_newer_than_windows81() -> bool {
unsafe {
let mut info: OSVERSIONINFOEX = { zeroed() };
info.dwOSVersionInfoSize = size_of::<OSVERSIONINFOEX>() as DWORD;
let mut info: OSVERSIONINFOEX = OSVERSIONINFOEX::default();
if RtlGetVersion(&mut info) == STATUS_SUCCESS {
info.dwMajorVersion > 6
if RtlGetVersion(&mut info) == NTSTATUS(0) {
info.dw_major_version > 6
} else {
false
}