Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Cannot call ApplicationViewTitleBar.SetBackgroundColor #2542

Closed
CXCubeHD opened this issue Jun 16, 2023 · 10 comments
Closed

Bug: Cannot call ApplicationViewTitleBar.SetBackgroundColor #2542

CXCubeHD opened this issue Jun 16, 2023 · 10 comments
Labels
question Further information is requested

Comments

@CXCubeHD
Copy link

Which crate is this about?

windows

Crate version

0.48.0

Summary

There seems to be no way to call ApplicationViewTitleBar.SetBackgroundColor.

Toolchain version/configuration

Default host: x86_64-pc-windows-msvc
rustup home: C:\Users\lukax.rustup

installed toolchains

stable-x86_64-pc-windows-msvc (default)
nightly-x86_64-pc-windows-msvc

installed targets for active toolchain

i686-pc-windows-msvc
x86_64-pc-windows-msvc

active toolchain

stable-x86_64-pc-windows-msvc (default)
rustc 1.67.0 (fc594f156 2023-01-24)

Reproducible example

let color = ColorHelper::FromArgb(255, 31, 19, 226)?;

match ApplicationView::GetForCurrentView()?
    .TitleBar()?
    .SetBackgroundColor(&color) {
    Ok(_) => {}
    Err(_) => {
        println!("Could not set BackgroundColor.");
    }
};

Crate manifest

[dependencies.windows]
version = "0.48.0"
features = [
    "ApplicationModel",
    "ApplicationModel_Core",
    "ApplicationModel_Activation",

    "Data_Xml_Dom",

    "Foundation",

    "Gaming",
    "Gaming_UI",

    "UI",
    "UI_Core",
    "UI_Notifications",
    "UI_ViewManagement",

    "System",

    "Win32_Foundation",
    "Win32_System_Threading",
    "Win32_System_LibraryLoader",
    "Win32_System_ProcessStatus",
    "Win32_System_Console",
    "Win32_System_SystemServices",
    "Win32_System_Threading",
    "Win32_Security",

    "Win32_Graphics",
    "Win32_Graphics_Dxgi",
    "Win32_Graphics_Dxgi_Common",
    "Win32_Graphics_Direct2D",
    "Win32_Graphics_Direct3D",
    "Win32_Graphics_Direct3D11",
    "Win32_Graphics_Direct3D11on12",
    "Win32_Graphics_Direct3D12",

    "Win32_Media_Audio",
    "Win32_Media_Audio_DirectSound",
]

Expected behavior

The code gets compiled.

Actual behavior

error[E0277]: the trait bound `windows::UI::Color: ComInterface` is not satisfied
    --> src\entry\mod.rs:85:37
     |
85   |                 .SetBackgroundColor(&color) {
     |                  ------------------ ^^^^^^ the trait `ComInterface` is not implemented for `windows::UI::Color`
     |                  |
     |                  required by a bound introduced by this call
     |
     = help: the following other types implement trait `ComInterface`:
               AccessibilitySettings
               ActivationViewSwitcher
               AdaptiveNotificationText
               ApplicationView
               ApplicationViewConsolidatedEventArgs
               ApplicationViewScaling
               ApplicationViewTitleBar
               ApplicationViewTransferContext
             and 1123 others
     = note: required for `&windows::UI::Color` to implement `TryIntoParam<windows::Foundation::IReference<windows::UI::Color>>`
note: required by a bound in `ApplicationViewTitleBar::SetBackgroundColor`
    --> C:\Users\lukax\.cargo\registry\src\github.com-1ecc6299db9ec823\windows-0.48.0\src\Windows\UI\ViewManagement\mod.rs:2212:13
     |
2212 |         P0: ::windows::core::TryIntoParam<super::super::Foundation::IReference<super::Color>>,
     |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ApplicationViewTitleBar::SetBackgroundColor`

Additional comments

Could not find any other ways to do that. Only thing that worked is &None I think

@CXCubeHD CXCubeHD added the bug Something isn't working label Jun 16, 2023
@CXCubeHD
Copy link
Author

It would super helpful if someone shows me a way to convert my color to IReference<windows::UI::Color>> properly

@kennykerr
Copy link
Collaborator

This is related to #292 - I'll see if I can find you a workaround for now.

@riverar riverar added question Further information is requested and removed bug Something isn't working labels Jun 16, 2023
@riverar
Copy link
Collaborator

riverar commented Jun 16, 2023

This requires boxing up the Windows.UI.Color value and implementing various interfaces, such as IReference, IPropertyValue, ComInterface, etc. There's no easy way to do that right now.

I'd like to warn you now, however, that using Windows.UI.* APIs for UI is a dead end. Universal Windows Apps are on the way out, so to speak, and these APIs were designed to be consumed by C#. (We recently abandoned an effort to provide bindings for newer/alternate WinUI 3 APIs.) I think you might find it more productive to instead use an alternate UI stack with Rust, such as Tauri (web-based) or Dear ImGui (immediate mode DirectX, Win32 GDI, etc).

@CXCubeHD
Copy link
Author

This requires boxing up the Windows.UI.Color value and implementing various interfaces, such as IReference, IPropertyValue, ComInterface, etc. There's no easy way to do that right now.

I will see if I can do a workaround by embedding C++

I'd like to warn you now, however, that using Windows.UI.* APIs for UI is a dead end. Universal Windows Apps are on the way out, so to speak, and these APIs were designed to be consumed by C#. (We recently abandoned an effort to provide bindings for newer/alternate WinUI 3 APIs.) I think you might find it more productive to instead use an alternate UI stack with Rust, such as Tauri (web-based) or Dear ImGui (immediate mode DirectX, Win32 GDI, etc).

I am only using Windows.UI for a really small amount of things like changing the title of a CoreWindow.

@kennykerr
Copy link
Collaborator

Today, the windows-core crate provides boxing for primitive types but not arbitrary WinRT types as C++/WinRT does. That shouldn't be too hard to add. Coming soon.

@kennykerr
Copy link
Collaborator

workaround by embedding C++

Note that you can use the implement macro to implement IReference<T> and IPropertyValue so there's no need to resort to C++.

The windows-core support I'm working on just means that those IReference parameters, modeling optional values, can be modeled as Option<T> in Rust.

@CXCubeHD
Copy link
Author

Note that you can use the implement macro to implement IReference<T> and IPropertyValue so there's no need to resort to C++.

How would I do that with windows::UI::Color?

@kennykerr
Copy link
Collaborator

Here's an example:

[dependencies.windows]
version = "0.48"
features = [
    "implement",
    "Foundation",
    "UI",
]
use windows::{core::*, Foundation::*, UI::*};

#[implement(IReference<T>, IPropertyValue)]
struct Reference<T>(T)
where
    T: RuntimeType + Clone + 'static;

impl<T: RuntimeType + Clone> IReference_Impl<T> for Reference<T> {
    fn Value(&self) -> Result<T> {
        Ok(self.0.clone())
    }
}

impl<T: RuntimeType + Clone> IPropertyValue_Impl for Reference<T> {
    fn GetInt16Array(&self, _: &mut Array<i16>) -> Result<()> {
        todo!()
    }
    fn GetUInt16Array(&self, _: &mut Array<u16>) -> Result<()> {
        todo!()
    }
    fn GetInt32Array(&self, _: &mut Array<i32>) -> Result<()> {
        todo!()
    }
    fn GetUInt32Array(&self, _: &mut Array<u32>) -> Result<()> {
        todo!()
    }
    fn GetInt64Array(&self, _: &mut Array<i64>) -> Result<()> {
        todo!()
    }
    fn GetUInt64Array(&self, _: &mut Array<u64>) -> Result<()> {
        todo!()
    }
    fn GetSingleArray(&self, _: &mut Array<f32>) -> Result<()> {
        todo!()
    }
    fn GetDoubleArray(&self, _: &mut Array<f64>) -> Result<()> {
        todo!()
    }
    fn GetChar16Array(&self, _: &mut Array<u16>) -> Result<()> {
        todo!()
    }
    fn GetBooleanArray(&self, _: &mut Array<bool>) -> Result<()> {
        todo!()
    }
    fn GetStringArray(&self, _: &mut Array<HSTRING>) -> Result<()> {
        todo!()
    }
    fn GetInspectableArray(&self, _: &mut Array<IInspectable>) -> Result<()> {
        todo!()
    }
    fn GetGuidArray(&self, _: &mut Array<GUID>) -> Result<()> {
        todo!()
    }
    fn GetDateTimeArray(&self, _: &mut Array<DateTime>) -> Result<()> {
        todo!()
    }
    fn GetTimeSpanArray(&self, _: &mut Array<TimeSpan>) -> Result<()> {
        todo!()
    }
    fn GetPointArray(&self, _: &mut Array<Point>) -> Result<()> {
        todo!()
    }
    fn GetSizeArray(&self, _: &mut Array<Size>) -> Result<()> {
        todo!()
    }
    fn GetRectArray(&self, _: &mut Array<Rect>) -> Result<()> {
        todo!()
    }
    fn GetTimeSpan(&self) -> Result<TimeSpan> {
        todo!()
    }
    fn GetPoint(&self) -> Result<Point> {
        todo!()
    }
    fn GetSize(&self) -> Result<Size> {
        todo!()
    }
    fn GetRect(&self) -> Result<Rect> {
        todo!()
    }
    fn GetUInt8Array(&self, _: &mut Array<u8>) -> Result<()> {
        todo!()
    }
    fn Type(&self) -> Result<PropertyType> {
        todo!()
    }
    fn IsNumericScalar(&self) -> Result<bool> {
        todo!()
    }
    fn GetUInt8(&self) -> Result<u8> {
        todo!()
    }
    fn GetInt16(&self) -> Result<i16> {
        todo!()
    }
    fn GetUInt16(&self) -> Result<u16> {
        todo!()
    }
    fn GetInt32(&self) -> Result<i32> {
        todo!()
    }
    fn GetUInt32(&self) -> Result<u32> {
        todo!()
    }
    fn GetInt64(&self) -> Result<i64> {
        todo!()
    }
    fn GetUInt64(&self) -> Result<u64> {
        todo!()
    }
    fn GetSingle(&self) -> Result<f32> {
        todo!()
    }
    fn GetDouble(&self) -> Result<f64> {
        todo!()
    }
    fn GetChar16(&self) -> Result<u16> {
        todo!()
    }
    fn GetBoolean(&self) -> Result<bool> {
        todo!()
    }
    fn GetString(&self) -> Result<HSTRING> {
        todo!()
    }
    fn GetGuid(&self) -> Result<GUID> {
        todo!()
    }
    fn GetDateTime(&self) -> Result<DateTime> {
        todo!()
    }
}

fn box_value<T: RuntimeType + Clone>(value: T) -> IReference<T> {
    Reference(value).into()
}

fn main() -> Result<()> {
    let red = Colors::Red()?;
    dbg!(red);
    
    let boxed = box_value(red);
    assert_eq!(boxed.Value()?, red);

    Ok(())
}

Depending on the API you're calling, you may need to implement some of the IPropertyValue methods but most can generally be ignored. Obviously, a production implementation should return E_NOTIMPL for unimplemented methods but this is just a quick sketch that should get you going.

As you can see, it's a bit involved which is why I'd like to just bake this in to accept Option<T>.

@CXCubeHD
Copy link
Author

@kennykerr Thank you soo much!

@riverar
Copy link
Collaborator

riverar commented Jun 21, 2023

Closing as complete for now; workaround above and we're tracking related work via #292.

@riverar riverar closed this as completed Jun 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants