0

Why does a LoadCursorA generate 'trait implementation' build errors when a LoadCursorW call does not when using the rust Crate for Windows?

#[allow(dead_code)]
use windows::Win32::UI::WindowsAndMessaging::LoadCursorA;
use windows::Win32::UI::WindowsAndMessaging::IDC_ARROW;

fn main() {
    unsafe {
        let _h_cursor = LoadCursorA(None, IDC_ARROW);
        //let _h_cursor = LoadCursorA(None, &IDC_ARROW);
    };
}

error[E0277]: the trait bound PWSTR: IntoParam<'_, PSTR> is not satisfied

IInspectable
  • 46,945
  • 8
  • 85
  • 181
MRahilly
  • 25
  • 3
  • Can you paste the compiler error also? – Abdul Niyas P M Nov 19 '21 at 11:41
  • 1
    Because [`IDC_ARROW` is a `PWSTR`](https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/UI/WindowsAndMessaging/constant.IDC_ARROW.html) and so cannot be used with the `…A` functions, which require a `PSTR`. – Jmb Nov 19 '21 at 13:45
  • Can the LoadCursorA call be modified to build and if so how? Thanks. – MRahilly Nov 19 '21 at 16:48
  • `IDC_*` constants are not really pointers but short integer constants disguised as pointers, so you should be safe doing `IDC_ARROW as PSTR`. – rodrigo Nov 19 '21 at 18:58
  • Trying IDC_ARROW as PSTR gives error[E0605] non-primitive cast: `PWSTR` as `PSTR` – MRahilly Nov 20 '21 at 11:07
  • `PSTR(IDC_ARROW.0 as _)` should work for the conversion. – Jmb Nov 22 '21 at 07:35

1 Answers1

3

The reason IDC_ARROW doesn't work with LoadCursorA is because it is a PWSTR, so it can only work with …W functions. Functions in …A need a PSTR instead.

However IDC_ARROW is not really a PWSTR (ie. a "pointer to wide-character string"). It's just a small constant masquerading as a PWSTR, so we can convert it to a PSTR and pass that to LoadCursorA:

#[allow(dead_code)]
use windows::Win32::UI::WindowsAndMessaging::LoadCursorA;
use windows::Win32::UI::WindowsAndMessaging::IDC_ARROW;

fn main() {
    unsafe {
        let _h_cursor = LoadCursorA(None, PSTR(IDC_ARROW.0 as _));
    };
}

Of course another option is just to use LoadCursorW instead:

#[allow(dead_code)]
use windows::Win32::UI::WindowsAndMessaging::LoadCursorW;
use windows::Win32::UI::WindowsAndMessaging::IDC_ARROW;

fn main() {
    unsafe {
        let _h_cursor = LoadCursorW(None, IDC_ARROW);
    };
}
Jmb
  • 18,893
  • 2
  • 28
  • 55