rodrigocfd / winsafe Goto Github PK
View Code? Open in Web Editor NEWWindows API and GUI in safe, idiomatic Rust.
Home Page: https://crates.io/crates/winsafe
License: MIT License
Windows API and GUI in safe, idiomatic Rust.
Home Page: https://crates.io/crates/winsafe
License: MIT License
Currently, this crate only has a wrapper around ChangeDisplaySettingsW, which is limited to changing device settings for the "Default" or primary display. However this crate already provides EnumDisplaySettingsExW that allows you to retrieve the DEVMODE struct for any display
This issue proposes adding ChangeDisplaySettingsExW which takes in a parameter to specify the device name so that one can both read and write device settings for all displays
lpParam needs to be a valid pointer in some cases:
If an application calls CreateWindow to create a MDI client window, lpParam should point to a CLIENTCREATESTRUCT structure. If an MDI client window calls CreateWindow to create an MDI child window, lpParam should point to a MDICREATESTRUCT structure. lpParam may be NULL if no additional data is needed.
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw
However, CreateWindowEx
is not unsafe
, performs no relevant parameter validation, and makes lparam a simple to misconstruct Option<isize>
.
winsafe/src/user/handles/hwnd.rs
Lines 123 to 135 in 04769f7
Also, how does one use SetClipboardData
?
I tried this:
fn events(&self) {
self.btn_hello.on().bn_clicked({
let self2 = self.wnd.clone(); // clone so it can be passed into the closure
move || {
let mut ptr = b"Hello World\0".to_vec().as_mut_ptr() as *mut u8;
self2.hwnd().OpenClipboard();
SetClipboardData(CF::TEXT, ptr);
CloseClipboard();
(modified from https://github.com/rodrigocfd/winsafe-examples/blob/941627b5ea93d7e7e564c91478a88a1d64e2dcf4/01_button_click/src/my_window.rs#L38-L41)
But when I click the button, the program crashes with:
error: process didn't exit successfully: `target\debug\app.exe` (exit code: 0xc0000374, STATUS_HEAP_CORRUPTION)
For example, the msctls_progress32
control does not seem to be supported yet. Is there a way to send custom messages to unsupported controls created in .resource
files, using this function?
Lines 973 to 982 in 82bcca0
In this specific case, I'd like to send PBM_SETSTEP
messages.
These two functions work in two stages: first they do the query with a null buffer to discover the type and length of the data, then they do the query a second time with an allocated buffer of the specified length. However, another process, or another thread of the same process, could have modified the value in the registry in between the two calls. Thus:
Furthermore, even in the absence of race conditions, there is no checking that the returned length makes sense for the given type. This is not guaranteed by the Windows API: it is totally possible to construct a REG_DWORD
that is three or seven bytes long, or a REG_SZ
whose length is odd or that does not end in a NUL. You can even do this in RegEdit by right-clicking a value and clicking Modify Binary. This lack of checking means that, for example, if the registry contains a three-byte REG_DWORD
, then when constructing the return value, u32::from_ne_bytes(buf.try_into().unwrap())
will panic because buf
is not four bytes long. This should be caught and returned as a proper error, since an application should never be forced to panic under the control of external data.
Does winsafe support creating TRACKMOUSEEVENT
?
I get an error related to private fields.
let mut mouse_event = winsafe::TRACKMOUSEEVENT {
dwFlags: winsafe::co::TME::HOVER | winsafe::co::TME::LEAVE,
hwndTrack: self.lbl.hwnd(),
dwHoverTime: 0,
..Default::default()
//^^^^^^^^^^^^^^^^^^^^ field `cbSize` is private
};
winsafe::TrackMouseEvent(&mut mouse_event);
let label_events = self.lbl.on_subclass();
label_events.wm_mouse_hover({
move |params| {
println!("{},{}", params.coords.x, params.coords.y);
}
});
ChangeDisplaySettings and ChangeDisplaySettingsEx should allow the dev_mode
parameter to be optional.
This is required for getting the default mode after a dynamic mode change. It is also required (and I can't find this in the docs anywhere) to apply changes to the display configuration.
I can listen for menu list open events. But what about for when a specific menu item is clicked? I dont see WM_MENUSELECT in the documentation.
My menu is created in a resource file, if it matters.
let name: u16 = // ?
let h_icon = HINSTANCE::NULL.LoadImageIcon(name, 16, 16, LR::LOADFROMFILE);
Why is name a u16
? Shouldn't a filename string be accepted?
I would like to change the window icon at runtime from a file that isn't included in the resources.
The wrapper for GetDlgCtrlId
tries to distinguish between zero-as-success and zero-as-failure by calling GetLastError
. However, it does not call SetLastError(ERROR_SUCCESS)
before calling GetDlgCtrlId
, which means if the last error code was non-successful on entry and the value is zero, a spurious error will be returned. The documentation is vague as to whether the last error code is cleared on success or not by the underlying Windows API call, but I encountered this personally and it is not, so you should probably do it in the wrapper.
It would be nice to have support for RegQueryMultipleValuesW
, since as far as I know that’s the only way to atomically read multiple values as a point-in-time snapshot.
It worked with v0.0.3 though: https://github.com/GirkovArpa/verpatch-gui-win32
In commit 8335fe2, you changed the pub_struct_msg_char
macro to generate a char_code
field of type co::VK
rather than u16
. That macros is used for lots of messages right now, but their wParam
s aren’t all the same!
WM_CHAR
gives a character code.WM_KEYDOWN
gives a virtual-key code.WM_KEYUP
gives a virtual-key code.WM_SYSCHAR
gives a character code.WM_SYSDEADCHAR
gives a character code.WM_SYSKEYDOWN
gives a virtual-key code.WM_SYSKEYUP
gives a virtual-key code.Only those that carry a virtual-key code should be of type VK
. The ones that carry a character code are either UTF-16 code units if the window class was registered with RegisterClassW
or RegisterClassExW
, or code page characters if registered with RegisterClassA
or RegisterClassExA
. So they should go back to being of type u16
(don’t use char
since some sources claim that a non-BMP character could be delivered by two consecutive WM_CHAR
messages each containing a surrogate, and a Rust char
cannot contain a surrogate, so each message on its own would fail to decode; only later after reassembling both messages do you actually have a complete character).
I think there is a memory leak in the 02_combo_and_radios
example, which might be best addressed in this repo rather than in the example. Remove the #[derive(Clone)]
from MyWindow
and implement that and Drop
by hand, with instrumentation, to see it:
pub struct MyWindow {
wnd: gui::WindowMain,
cmb_cities: gui::ComboBox,
rad_seas: gui::RadioGroup,
}
impl Clone for MyWindow {
fn clone(&self) -> Self {
println!("Clone");
Self {
wnd: self.wnd.clone(),
cmb_cities: self.cmb_cities.clone(),
rad_seas: self.rad_seas.clone(),
}
}
}
impl Drop for MyWindow {
fn drop(&mut self) {
println!("Drop");
}
}
When you run the code you see “Clone” printed three times (so there are four instances of MyWindow, the one created directly in MyWindow::new and then the three clones captured in event handler closures), but “Drop” is only printed once! So three objects have been leaked. The problem, if I understand correctly, is that there is a circular reference:
MyWindow
contains a gui::WindowMain
.WindowMain
contains a RawDlg
, in this case the RawDlg::Raw
variant.RawDlg::Raw
contains a RawMain
.RawMain
contains a Pin<Arc<Obj>>
.Obj
contains a RawBase
.RawBase
contains a Base
.Base
contains a WindowEventsAll
.WindowEventsAll
contains a FuncStore<(u16, co::NM), Box<dyn Fn(wm::Notify) -> AnyResult<Option<isize>>>
.FuncStore
contains a Vec<Pair>
with one element.Vec
contains a Box
.Box
contains a the closure passed to ComboBoxEvents::cbn_sel_change
.MyWindow
.So the Pin<Arc<Obj>>
in step 4 contains, via a very long chain, a reference to itself.
Application code could fix this if it was very careful: instead of cloning MyWindow
, it could hold MyWindow
behind an Rc
and always downgrade the Rc
to a Weak
and capture the Weak
as part of the closure, upgrading it on each call; thus step 12 would break the cycle (since the closure would only contain a Weak
). However, this is unintuitive and it would be easy to get it wrong.
I noticed you are only allowed to register event handlers before the HWND
has been created. I wonder, would it make any sense that, when the HWND
is destroyed, you drop all the event handlers? After all, if the HWND
has been destroyed, they aren’t needed any more (since no more events can be delivered to them), and dropping them would break the circular reference. Although I’m not sure how well that would work with dynamic creation and destruction of controls, since many event handlers conceptually belong to child windows (e.g. WM_COMMAND
handlers for buttons) but are actually registered against the parent (since that’s where the WM_COMMAND
is actually sent).
Hi, I'm trying to get a screenshot using winsafe, but there's no GetDIBits function, can it be added?
With windows-rs it looks atrocious:
let mut bmi = BITMAPINFO {
bmiHeader: BITMAPINFOHEADER {
biSize: std::mem::size_of::<BITMAPINFOHEADER>() as u32,
biWidth: bmp.bmWidth,
biHeight: -bmp.bmHeight,
biPlanes: 1,
biBitCount: 32,
biCompression: BI_RGB as u32,
biSizeImage: 0,
biXPelsPerMeter: 0,
biYPelsPerMeter: 0,
biClrUsed: 0,
biClrImportant: 0,
},
bmiColors: [RGBQUAD {
rgbBlue: 0,
rgbGreen: 0,
rgbRed: 0,
rgbReserved: 0,
}],
};
//let size: usize = (width * height) as usize * 4;
let size: usize = (((bmp.bmWidth * (bmi.bmiHeader.biBitCount as i32) + 31) / 32) * 4 * bmp.bmHeight) as usize;
let mut data: Vec<u8> = Vec::with_capacity(size);
unsafe { data.set_len(size) };
unsafe {
GetDIBits(
hdc_mem, hbmp, 0, height as u32, &mut data[0] as *mut u8 as *mut c_void,
&mut bmi,
DIB_RGB_COLORS,
);
}
I would like to handle MOUSEMOVE
for a label, but it doesn't have such an event. I don't think labels support custom messages like here, right?
I can't use self.wnd.on().wm_mouse_move({
because it stops firing when the cursor moves over a control.
It would be nice to have support for the transactional registry API, i.e. RegCreateKeyTransactedW
, RegOpenKeyTransactedW
, and the transaction manager APIs necessary to support them, i.e. CreateTransaction
, CommitTransaction
, and RollbackTransaction
.
Hey all
I'm trying to translate a piece of c++ code (https://stackoverflow.com/questions/59926644/listing-of-installed-apps-on-windows-10) to rust. In it the author uses the BindToHandler function. I found that method in this crate as well but the problem is that in the original c++ code they pass a nullptr for the bindcontext. Since the bind context parameter in the BindToHandler method is not an option I can't pass None like I did with SHCreateItemFromParsingName. What would be the equivalent here of passing a NULL value in c++?
kr
The lpPrivate field at the end here:
Lines 433 to 443 in 6540aea
Is only defined by windows.h if _MAC
(macos / OS X) is defined:
typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
#ifdef _MAC
DWORD lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;
On 64-bit, there's some implicit padding there anyways. That's a bit sketchy if MSG were ever to be combined with MaybeUninit, as lPrivate could end up being left uninitialized.
On 32-bit, this actually changes the struct size (winsafe::MSG is 32 bytes, windows.h MSG is 28 bytes.)
Perhaps use #[cfg(target_os = "macos")]
?
currently this repo indents with tabs, but the style guide recommends to use spaces (4, specifically).
this bugged me greatly because by default vscode with rust extension will do 'format document' automatically upon every save, and it tries to convert all the indenting tabs to spaces.
there are two options i'd like to recommend:
cargo fmt
run to get a sane-enough outcome now
rustfmt.toml
added to the repo with hard_tabs
set to true
just my two cents!
I'd like to request a wrapper for GetVolumeInformation/GetVolumeInformationA/GetVolumeInformationW. Probably the last one, since that speaks Unicode.
(Use case: I need to do something cross-plaform, but don't have a modern Windows dev environment. So I want to cross-compile. Thanks.)
The event is missing from the list in the documentation:
https://rodrigocfd.github.io/winsafe/winsafe/msg/lb/index.html
But it's in the Microsoft documentation:
https://docs.microsoft.com/en-us/windows/win32/controls/lb-setsel
I think it should look something like this:
winsafe::msg::lb::SetCurSel {
select: bool,
index: u32
}
Without it, there's no guaranteed way to uniquely select an item by index. SelectString
can be used to select the first item beginning with a certain string, but fails to select Hello
if that item is preceded by Hello World!
.
Correct me if I'm wrong ...
It would be nice if there were a clean way to build most of a GUI using the safe, high-level gui
module, but include one or two controls that are not supported by Winsafe (either Microsoft common controls that Winsafe doesn’t wrap yet, or perhaps third-party controls in a linked DLL). Here are the ways I could think of to achieve that, along with why they’re not ideal:
WindowControl::new
because it insists on registering the class, which is inappropriate for an already-registered class.CreateWindowEx
with no control ID, you can’t use .on().wm_notify(…)
to receive WM_NOTIFY
messages relating to the control because you have no control ID, which is a mandatory parameter to the wm_notify
method.CreateWindowEx
with no control ID, you can’t use .on().wm(WM::NOTIFY, ...) and match the HWND
in the NMHDR
, because callbacks registered with .wm(WM::NOTIFY, …)
don’t seem to get called at all (it seems like WM_NOTIFY
must be special-cased and not handleable via general-purpose message handlers).CreateWindowEx
with a control ID, it works, but the auto-generated control IDs that Winsafe uses under the hood for the gui
module are not available for clients to allocate and the value range is undocumented AFAICT, so it’s impossible to choose a safe, non-colliding control ID purely from publicly documented information.As you can see in the code below, parms.hwnd
is always the handle to my label, because it's the only control on the window. But the text is still black, not red as intended. Is this a bug, just an unsupported feature, or am I doing something wrong?
I've tried to translate what I've read on stackoverflow into the corresponding winsafe version. The answers there say to return an HBRUSH
, but the compiler says it must return an HDC
, so I figured setting the brush of the HDC
is equivalent.
self.wnd.on().wm_ctl_color_static({
let self2 = self.clone();
move |parms| {
println!("{:?}", parms.hwnd == self2.lbl.hwnd()); // true
let red = COLORREF::new(0xff, 0x00, 0x00);
let brush = HBRUSH::CreateSolidBrush(red).unwrap();
parms.hdc.SelectObjectBrush(brush);
parms.hdc.SetTextColor(red).unwrap();
parms.hdc.SetBkMode(winsafe::co::BKMODE::TRANSPARENT);
parms.hdc
}
});
Windows 11, rust, added winsafe with gui feature, copy-pasted code from readme, cargo.exe build, cargo.exe run
rustc 1.64.0-nightly (1c7b36d4d 2022-07-12)
binary: rustc
commit-hash: 1c7b36d4db582cb47513a6c7176baaec1c3346ab
commit-date: 2022-07-12
host: x86_64-pc-windows-msvc
release: 1.64.0-nightly
LLVM version: 14.0.6
> cargo.exe run
Compiling winsafe v0.0.11
Compiling test v0.1.0 (<path>)
Finished dev [unoptimized + debuginfo] target(s) in 15.00s
Running `target\debug\test.exe`
error: process didn't exit successfully: `target\debug\test.exe` (exit code: 0xc0000138, STATUS_ORDINAL_NOT_FOUND)
With latest master:
> cargo.exe run
Updating git repository `https://github.com/rodrigocfd/winsafe`
Compiling winsafe v0.0.11 (https://github.com/rodrigocfd/winsafe#7c14269e)
Compiling test v0.1.0 (<path>)
Finished dev [unoptimized + debuginfo] target(s) in 22.23s
Running `target\debug\test.exe`
error: process didn't exit successfully: `target\debug\test.exe` (exit code: 0xc0000138, STATUS_ORDINAL_NOT_FOUND)
It’s a useful function to have around, as a more modern replacement for GetSystemMetrics
.
hi
I'm trying to use the BindToHandler method to iterate over objects in a folder. According to the examples I have found I should use the EnumItems BHID for that. But that constant requires the IEnumShellItems interface which I don't believe is supported in this library. I have attemtped to use IShellItemArray instead like so let ish_arr = shi.BindToHandler::<IShellItemArray>(None, &BHID::EnumItems).unwrap();
but then I get a No such interface supported
.
Is there an alternative to this or will this interface be supported in the near-future?
Thanks!
Hey, thank you for working on this project, its great !.
I am playing around with winapi in general for learning, so what is the correct way to send mouse and key events to a window since I could use this in a work project for automation of an app at work , it is already in production but I used global key events so this would be better using direct msg .
I wonder if this should work, cuz it doss not seem to work for me no right click happens,
and the FindWindow function should not not have the class name as an Optional?
and is the xy cords relative to the window or the screen? Thank you :)
rs```
let hwnd = HWND::FindWindow("Notepad", "Untitled - Notepad")?;
hwnd.SetForegroundWindow();
hwnd.SetFocus();
let m = wm::RButtonDown {
vkey_code: co::VK::RBUTTON,
coords: POINT { x: 8, y: 8 },
};
hwnd.SendMessage(m);
would it be safe to cast Char::char_code
as u16
?
basically i'm thinking of:
use winsafe::{
co::VK,
msg::wm::Char,
prelude::*
};
ctl_edit.on_subclass().wm_char({
move |char_info: Char| -> ErrResult<()> {
if VK::from(char_info.char_code as u16) == VK::RETURN { // u16 casting safe??
// user pressed enter inside this edit control
}
todo!() // TODO: fill in
}
});
How to show the file open dialog?
let mut foo: winsafe::IUnknown = winsafe::CoCreateInstance(
&winsafe::shell::clsid::FileOpenDialog,
None,
winsafe::co::CLSCTX::INPROC_SERVER,
).unwrap();
This code runs without errors but doesn't show a file open dialog.
I would like to keep using Rust instead of switching to C#, but I never did any win32 programming so winsafe is very helpful. I've looked into webview2-rs, but the public API is full of unsafe
and I found the sample code too complicated compared to winsafe...
Could WebView2 be added to winsafe somehow? I understand WebView2 is very new relative to the classic controls, but I think it would be pretty amazing, if it's doable.
Sending window messages in general should be unsafe
. DispatchMessage
- among others - is not.
Lines 100 to 103 in 06b1c08
While the underlying DispatchMessage does a lot of parameter checking - including forbidding most system messages that interpret wparam/lparam as pointers by returning ERROR_MESSAGE_SYNC_ONLY
- it cannot do the same for WM_USER+n or WM_APP+n messages which might interpret wparam/lparam as pointers.
For example, Microsoft's own TOOLBARCLASSNAME
("ToolbarWindow32"
) expects wparam
to be a pointer to an array for TB_ADDBUTTONSW (WM_USER+68). While the docs recommend using SendMessage, DispatchMessage also works, and can crash / access violation if fed an invalid pointer. Other messages could even mutate what's pointed to, causing random memory corruption instead of a nice and clean access violation.
This means that if any middleware, library, injected DLL, etc. might ever create a window containing a toolbar on one of your threads, you can use DispatchMessage to cause undefined behavior.
SendMessage and DefWindowProc have similar issues, although there are traits involved muddying things up. Additionally, SendMessage won't reject messages with ERROR_MESSAGE_SYNC_ONLY to my knowledge. The traits involved are "safe" - it appears you're able to implement them to use e.g. WM::SETTEXT without any unsafe
, despite the possibility of passing an invalid pointer in wparam for the string text.
PostThreadMessage at least won't dispatch to a wndproc... but I promise you that third parties will inject threads into your process (game overlays, debuggers, ...), and will treat wparam/lparam as pointers for some WM_USER+N messages.
The RAII guard for an HDWP
returned by BeginDeferWindowPos
is implemented the same way as lots of other RAII guards. However, in the case of an HDWP
, that is incorrect for two reasons:
DeferWindowPos
, “The handle returned by this function may differ from the handle passed to the function. The new handle that this function returns should be passed during the next call to the DeferWindowPos or EndDeferWindowPos function.” In other words, the old handle must not be ended nor reused, and the new handle (which DeferWindowPos
currently returns as an unguarded HDWP
) must be ended. What should probably ideally happen is that the handle living in the guard is swapped out for the return value on each call, and maybe DeferWindowPos
should return SysResult<()>
instead of SysResult<HDWP>
.EndDeferWindowPos
.RegOpenKeyEx
always returns a null HKEY
on success. The problem is that a null HKEY
is constructed, then hKey.as_ptr()
is passed into the raw function, which means it will store the newly opened HKEY
into wherever hKey
pointed at, which is null, rather than into hKey
itself. I changed the function to look like this and it now works, but I imagine raw types like c_void
probably aren’t supposed to appear here; I just don’t really quite understand all the type aliases so it was the fastest and simplest fix I could come up with:
fn RegOpenKeyEx(self, sub_key: &str,
options: co::REG_OPTION, access_rights: co::KEY) -> SysResult<HKEY>
{
let mut hKey: *mut std::ffi::c_void = std::ptr::null_mut();
match co::ERROR(
unsafe {
advapi::ffi::RegOpenKeyExW(
self.as_ptr(),
WString::from_str(sub_key).as_ptr(),
options.0,
access_rights.0,
&mut hKey as _,
)
} as _,
) {
co::ERROR::SUCCESS => Ok(unsafe { HKEY::from_ptr(hKey) }),
err => Err(err),
}
}
It would be nice to have a GetMonitorInfo function on the HMONITOR struct that supports MONITORINFOEX as an input, or make the existing function support it.
It would be nice to have a wrapper in the gui
module for the tab common control.
I created the resource file in Resource Hacker, and saved the label with the SS_CENTER
flag:
But in the program it's displayed as left-aligned:
Code:
myself.lbl.set_text(&myself.input_val.borrow()).unwrap();
Create a WindowControl
without setting WindowControlOpts::ctrl_id
to anything. The documentation says a control ID will be auto-generated; in actual fact, the window is created with a child ID of zero. It works for other controls (at least the ones I checked), just not WindowControl
.
The EnumDisplayDevices function returns a WinResult. I don't see where Ok(true)
is ever set. It also seems like it is not required because we also return a result.
Also, the current example in the docs of that function is a bit weird. The function is supposed to be called until the first error because that means that we finished iterating over all displays:
if !is_finished {
will never be the case, because the ?
will return the error.
This is a great piece of work.
But how do you set the bk color of a label (or set the mode to transparent)?
An example would be very helpful. Thanks!
Hi,
when you say that "WinSafe works with both ordinary windows and resource dialogs", does it mean that it will be possible to use a tool like ResEdit to create the GUI visually (or parts of it..) with it's dialog editor and use the .rc file created ?
when changing rust toolchain to "stable-i686-pc-windows-msvc" I get this ( error: linking with link.exe
failed: exit code: 1120 )
Hello world app builds fine with the mentioned toolchain, but can't build with winsafe dependency.
Lots of things that take a handle take it by reference, since the commit that made handles non-Copy
and non-Clone
—for example, SetParent
takes an &HWND
as the new parent, not an HWND
. RegCreateKeyTransacted
and RegOpenKeyTransacted
currently take the HTRANSACTION
by value; it probably makes sense for them to take it by reference instead, to avoid ugly calls to raw_copy
in user code.
Currently EnumDisplaySettingsExW is provided by this crate, but it is not possible to enumerate the settings of multiple displays since EnumDisplayDeviceW is not provided.
Adding this to the list will be beneficial for applications that need to make use of multiple displays
lb::InsertString only accepts a string, but the official documentation states that it also accepts an index.
Without being able to specify the index, emulating "update" functionality does not seem possible (deleting an item, then inserting an updated version at the same index).
The index seems to be hard-coded as 0
:
Line 615 in 82bcca0
The fact that you can close a handle and then keep using it (since e.g. RegCloseKey
takes self
by value, but HANDLE
impls Copy
so you can keep using the value afterwards anyway) seems unsound. Immediate reuse generally results in the invalid handle error being reported, but if you wait and reuse it later after other code has run, the handle value might match a newly opened handle. That new handle would definitely point at the wrong thing (e.g. a registry key handle opened for one key, when reused, would now modify a totally different key), and might even be the wrong type (e.g. a registry key handle might now refer to a file instead). This seems like it should probably be considered to violate memory safety.
I know this is probably more of a newbie rustacean issue, but I've tried match
without any luck:
let color: winsafe::COLORREF = winsafe::COLORREF::new(0xff, 0x00, 0x00);
let brush: winsafe::HBRUSH = GdiHbrush::CreateSolidBrush(color).unwrap();
^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
I'm trying to set the main window's background color.
Is there a specific reason why the getter for DeviceID
and DeviceKey
was removed from the DISPLAY_DEVICE
struct?
Seems like it happened here: 806c575#diff-61500d78eb074804b61d228b17c595974dd7cd10099a3cf8874919aee6239750R427
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.