summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/client/app/src/ui/windows/gdi.rs
blob: 89828987bc11cd305c40543023152e1960c4b741 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! GDI helpers.

use windows_sys::Win32::{
    Foundation::HWND,
    Graphics::Gdi::{self, GDI_ERROR, HDC, HGDIOBJ},
};

/// A GDI drawing context.
pub struct DC {
    hwnd: HWND,
    hdc: HDC,
}

impl DC {
    /// Create a new DC.
    pub fn new(hwnd: HWND) -> Option<Self> {
        let hdc = unsafe { Gdi::GetDC(hwnd) };
        (hdc != 0).then_some(DC { hwnd, hdc })
    }

    /// Call the given function with a gdi object selected.
    pub fn with_object_selected<R>(&self, object: HGDIOBJ, f: impl FnOnce(HDC) -> R) -> Option<R> {
        let old_object = unsafe { Gdi::SelectObject(self.hdc, object) };
        if old_object == 0 || old_object == GDI_ERROR as isize {
            return None;
        }
        let ret = f(self.hdc);
        // The prior object must be selected before releasing the DC. Ignore errors; this is
        // best-effort.
        unsafe { Gdi::SelectObject(self.hdc, old_object) };
        Some(ret)
    }
}

impl Drop for DC {
    fn drop(&mut self) {
        unsafe { Gdi::ReleaseDC(self.hwnd, self.hdc) };
    }
}