简体   繁体   English

我应该尝试在 Windows 的 Rust Crate 中的 CoreApp 的 PointerPressed 事件处理程序中访问 self 吗?

[英]Should I try to access self in a PointerPressed event handler for a CoreApp in the Rust Crate for Windows?

E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement. E0759 self 有一个匿名生命周期 '_ 但它需要满足一个 '静态生命周期要求。 E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement. E0759 self 有一个匿名生命周期 '_ 但它需要满足一个 '静态生命周期要求。 E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement. E0759 self 有一个匿名生命周期 '_ 但它需要满足一个 '静态生命周期要求。 E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement. E0759 self 有一个匿名生命周期 '_ 但它需要满足一个 '静态生命周期要求。

#![windows_subsystem = "windows"]

use windows::{
    core::*,
    Foundation::*,
    ApplicationModel::Core::*,
    Foundation::Numerics::*,
    Foundation::TypedEventHandler,
    Win32::System::Com::*,
    UI::{
        Core::*,
        Composition::*,
    },
    
};

use windows as Windows;

#[implement(Windows::ApplicationModel::Core::IFrameworkViewSource)]
struct App();

#[allow(non_snake_case)]
impl App {
    fn CreateView(&self) -> Result<IFrameworkView> {
        // TODO: need self query `self.into()` to support implementing both IFrameworkViewSource and IFrameworkView on the same object.
        Ok(AppView::new().into())
    }
}

#[implement(Windows::ApplicationModel::Core::IFrameworkView)]
struct AppView {
    m_target: Option<CompositionTarget>,
    m_visuals: Option<VisualCollection>,
    m_selected: Option<Visual>,
    m_offset: Option<Vector2>,
}

#[allow(non_snake_case)]
impl AppView {
    fn new() -> Self {
        Self {
            m_target: None,
            m_visuals: None,
            m_selected: None,
            m_offset: None,
        }
    }

    fn Initialize(&self, _: &Option<CoreApplicationView>) -> Result<()> {
        Ok(())
    }

    fn Load(&self, _: &HSTRING) -> Result<()> {
        Ok(())
    }

    fn Uninitialize(&self) -> Result<()> {
        Ok(())
    }

    fn Run(&self) -> Result<()> {
        let window = CoreWindow::GetForCurrentThread()?;
        window.Activate()?;

        let dispatcher = window.Dispatcher()?;
        dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit)?;

        Ok(())
    }

    fn SetWindow(&mut self, window: &Option<CoreWindow>) -> Result<()> {
        let compositor = Compositor::new()?;
        let root = compositor.CreateContainerVisual()?;
        self.m_target = Some(compositor.CreateTargetForCurrentView()?);
        let target = self.m_target.as_ref().unwrap();
        target.SetRoot(&root)?;
        self.m_visuals = Some(root.Children()?);
        let visuals = self.m_visuals.as_ref().unwrap(); // extra line for test is ok
        window.as_ref().unwrap().PointerPressed(TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, args|
            {
                let args = args.as_ref().unwrap();
                let currentpoint = args.CurrentPoint().unwrap();
                let point = currentpoint.Position().unwrap(); // Point not Vector2

                //let visuals: &VisualCollection = self.m_visuals.as_ref().unwrap();
                let visuals = self.m_visuals.as_ref().unwrap(); // E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement

                Ok(())
            }
        ))?;
        window.as_ref().unwrap().PointerMoved(TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, _args|
            {
                Ok(())
            }
        ))?;
        window.as_ref().unwrap().PointerReleased(TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, _args|
            {
                Ok(())
            }
        ))?;

        Ok(())
    }

    fn AddVisual(_point: Point) {
        //...
    }
}

fn main() -> Result<()> {
    unsafe {
        CoInitializeEx(std::ptr::null_mut(), COINIT_MULTITHREADED)?;
    }

    let app: IFrameworkViewSource = App().into();
    CoreApplication::Run(app)?;
    Ok(())
}

Capturing AppView's instance self reference in v0.30 doesn't seem to be possible, because TypedEventHandler::new has a + 'static requirement for the callback ( see ), so any reference it captures must be 'static (a global variable basically).在 v0.30 中捕获 AppView 的实例自引用似乎是不可能的,因为TypedEventHandler::new对回调有+ 'static要求( 请参阅),因此它捕获的任何引用都必须是'static (基本上是全局变量) .

Please raise an issue here if you want this.如果你想要这个,请在这里提出一个问题。 Your code looks like a reasonable way to use this API.您的代码看起来是使用此 API 的合理方式。

Until then, as a workaround you could make a level of indirection, where instead of storing the state directly in AppView, you store it in a shared helper object, for example:在此之前,作为一种解决方法,您可以进行一定程度的间接操作,而不是将 state 直接存储在 AppView 中,而是将其存储在共享帮助程序 object 中,例如:

struct AppView {
    m_state: Rc<RefCell<AppViewState>>,
}

struct AppViewState {
    m_target: Option<CompositionTarget>,
    m_visuals: Option<VisualCollection>,
    m_selected: Option<Visual>,
    m_offset: Option<Vector2>,
}

You can clone it move into the callback for modification:您可以将其克隆到回调中进行修改:

let pointer_pressed_state = Rc::clone(self.m_state);
let pointer_pressed_handler = TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, args| {
    let state_ref = pointer_pressed_state.borrow(); // or .borrow_mut()
    ...
});

let pointer_moved_state = Rc::clone(self.m_state);
let pointer_moved_handler = TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, args| {
    let state_ref = pointer_moved_state.borrow(); // or .borrow_mut()
    ...
});

This should work, because now the closure doesn't capture any references (everything gets moved).这应该可行,因为现在闭包不会捕获任何引用(一切都被移动了)。

If you want, you can add methods to AppViewState, and call them from the closures like state_ref.OnPointerPressed(...) .如果需要,您可以向 AppViewState 添加方法,并从state_ref.OnPointerPressed(...)之类的闭包中调用它们。

Another option that I don't recommend is to use unsafe and cast self to 'static.我不推荐的另一个选择是使用 unsafe 并将 self 转换为 'static.

Rc<RefCell> gives a thread related compiler error but changing to Arc<Mutex> resolves this. Rc<RefCell> 给出线程相关的编译器错误,但更改为 Arc<Mutex> 可以解决此问题。

struct AppView {
    m_state: Arc<Mutex<AppViewState>>,
}

struct AppViewState {
    m_target: Option<CompositionTarget>,
    m_visuals: Option<VisualCollection>,
    m_selected: Option<Visual>,
    m_offset: Option<Vector2>,
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 Windows 的 Rust 板条箱中为 CoreApp 注册 PointerPressed 事件处理程序? - How do you register a PointerPressed event handler for a CoreApp in the Rust Crate for Windows? 如何使用 Windows 的 Rust 板条箱将 CompositionTarget 初始化为 null? - How do I initialize a CompositionTarget to null using the Rust Crate for Windows? 从 Rust Windows 二进制包导出 function - Export function from Rust Windows binary crate 如何为 RegGetValueW 分配内存(通过 Windows crate for Rust) - How to allocate memory for RegGetValueW (via the Windows crate for Rust) 如何分配空间以使用 windows 板条箱调用 GetInterfaceInfo? - How do I allocate space to call GetInterfaceInfo using the windows crate? 当showdialogwindow阻止我尝试访问的窗口时,是否存在可以使用的事件或事物 - Is there an event or something i can use when a showdialogwindow is blocking the window i try to access Windows下的全局异常处理程序(访问冲突) - Global exception handler (access violations) under Windows 错误 [E0463]: can&#39;t find crate for std... 如何在 x64 Windows 机器上编译 Rust x32? - Error[E0463]: can't find crate for std... how to compile Rust x32 in a x64 Windows machine? 如何在Windows上为C中的访问冲突错误安装信号处理程序? - How do I install a signal handler for an access violation error on Windows, in C? 为什么当我尝试打开删除挂起的文件时 Windows 返回 ERROR_ACCESS_DENIED - Why does Windows return ERROR_ACCESS_DENIED when I try to open a delete pended file
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM