Git Product home page Git Product logo

Comments (5)

rodrigocfd avatar rodrigocfd commented on May 23, 2024 1

Many years ago, when I was still writing WinLamb, I looked into MFC headers and I found that it allowed the Resource Editor to auto-generate user IDs up to 19,999. So WinSafe auto-generated IDs start at 20,000, giving the user the same range given by MFC, as you can see here.

This behavior should be documented though, I'll write it down now.

from winsafe.

rodrigocfd avatar rodrigocfd commented on May 23, 2024

Ideally, all native controls should be supported by WinSafe. I plan to implement them all, the next one being this one you suggested (hard stuff, but it will be fun to implement).

As for third-party DLL controls, I never worked with one of those, so I have no idea how they interact with the window message loop, which is the heart of the window and all its child controls. I imagine those third-party controls expose some C functions, and have some hooks (possibly callbacks) to process messages and return whether they processed them or not. Anyway, I'd like to see one of those, and learn how they work.

Indeed, all 4 points you consider refer to the very same problem I cited in the paragraph above: how to expose the window message loop. Currently, it is exposed through the on() method, which adds entries to the core message loop. These entries are then executed when the internal WndProc is called by the OS.

The WindowControl abstraction is the most flexible control I could conceive. Basically, it's a blank canvas which you can paint and treat input the way you want, and handle the messages any way you want. For exotic/specific controls, it should suffice. However, for controls already written in C, that's a whole new world I never dealt with, as I said before.

What are you trying to do, specifically?

from winsafe.

Hawk777 avatar Hawk777 commented on May 23, 2024

What I’m actually trying to accomplish right now is using a tab control. I totally agree that the ideal case is that all the Microsoft common controls have wrappers in the gui module, and I’ll be happy to use that in future once it’s available. I just figured there would be a reasonable option available before that time, namely a way to handle arbitrary controls.

I don’t actually know for sure how third-party controls tend to work in practice; I’ve never used one. I just figured they would work somewhat similarly to the Microsoft common controls:

  1. The application calls some kind of magic initialization function provided by the library (akin to InitCommonControlsEx), which calls RegisterClassEx for all the kinds of controls available in the library. This might have to be done via C FFI or whatever, but it is a single straightforward function call.
  2. The application instantiates the control with CreateWindowEx by specifying the relevant class.
  3. The application asks the control to do things by sending it messages.
  4. The control handles e.g. keyboard input while it has focus and mouse events over its rectangle by having its own window proc registered in its class, which DispatchMessage sends messages to (so Winsafe would never see them or need to worry about them).
  5. The application gets notified of the control doing things by receiving WM_COMMAND or WM_NOTIFY messages to the parent window.

So, if this is actually realistic, then to handle such things in Winsafe, what one would want is basically exactly the same as WindowControl, except don’t register a class when creating it, just create it using a class that already exists.

from winsafe.

rodrigocfd avatar rodrigocfd commented on May 23, 2024

Turns out, you can.

Taking this example as the baseline, I created a dynamic, arbitrary button with CreateWindowEx:

use std::cell::RefCell;
use std::rc::Rc;
use winsafe::{prelude::*, self as w, co, gui};

#[derive(Clone)]
pub struct MyWindow {
   wnd:  gui::WindowMain,
   hbtn: Rc<RefCell<w::HWND>>,
}

const ID_BTN: u16 = 2000;

impl MyWindow {
   pub fn new() -> Self {
      let wnd = gui::WindowMain::new(
         gui::WindowMainOpts {
            title: "My window title".to_owned(),
            class_icon: gui::Icon::Id(101),
            size: w::SIZE::new(300, 150),
            ..Default::default()
         },
      );

      let new_self = Self { wnd, hbtn: Rc::new(RefCell::new(w::HWND::NULL)) };
      new_self.events(); // attach our events
      new_self
   }

   pub fn run(&self) -> gui::MsgResult<i32> {
      self.wnd.run_main(None) // simply let the window manager do the hard work
   }

   fn events(&self) {
      let self2 = self.clone();
      self.wnd.on().wm_create(move |_| {
         *self2.hbtn.borrow_mut() = unsafe {
            w::HWND::CreateWindowEx(
               co::WS_EX::NoValue,
               w::AtomStr::Str(w::WString::from_str("BUTTON")),
               Some("&Click me"),
               co::WS::CHILD | co::WS::VISIBLE | co::WS::TABSTOP
                  | co::WS::GROUP | co::BS::PUSHBUTTON.into(),
               w::POINT::new(20, 20),
               w::SIZE::new(90, 30),
               Some(self2.wnd.hwnd()),
               w::IdMenu::Id(ID_BTN),
               &self2.wnd.hwnd().hinstance(),
               None,
            )
         }?;

         Ok(0)
      });

      let self2 = self.clone();
      self.wnd.on().wm_command(co::BN::CLICKED, ID_BTN, move || {
         self2.wnd.hwnd().MessageBox("Clicked!", "Clicking", co::MB::ICONINFORMATION)?;
         Ok(())
      });
   }
}

Notice I used the raw on().wm_command() event to handle the button click. Since you want a tab control, you'll have to handle all its messages properly. I used a tab control once, and I remember it was very tricky.

I plan to implement the tab control in the library, but if you need it now, you can crack it up after this example.

from winsafe.

Hawk777 avatar Hawk777 commented on May 23, 2024
const ID_BTN: u16 = 2000;

How did you know to choose 2000? How did you know that 2000 wouldn’t collide with winsafe’s internal ID number allocation?

from winsafe.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.