Ain't It Funny?

You haven’t “fooled” rustc, you are using unsafe code. Unsafe code means that all you can do is fool yourself. Or, and that’s the case here where passing HWND between threads should probably be fine, as you noted, you’ve simply used an overly “tricky” way to achieve the same thing you could’ve just told the compiler directly as an unsafe code user:

A pointer not being Send in Rust is mostly a precaution that unsafe Rust authors don’t accidentally make their non-threadsafe data structures implement Send. Since you’re using unsafe anyways, you can just as well create a struct containing the pointer, mark that struct Send unsafely, and thus arrive at a better solution than the one involving the usize case, since ptr->int->ptr casts can (at least in principle) have negative effects on what optimizations are possible.

Without using unsafe, a raw pointer is useless anyways; you can’t really do anything (useful) to it, in particular nothing that might dereference it.

Talking about safe Rust… I’m not familiar with win-API so I can’t judge the crate, but I did come across https://crates.io/crates/winsafe just googling for “HWND” in Rust, and their HWND in winsafe - Rust type is a safe wrapper around that pointer that does implement Send. (I.e. essentially following the “create a struct containing the pointer, mark that struct Send” approach I mentioned above.)