Barnabás
Barnabás

Reputation: 13

Cannot hide taskbar when there is another docked app on screen

I created a simple window in rust with the win32 api and docked it to the top of the screen using the shell api. But if I run this code, after the window has been created the taskbar reappears immediately and I cannot set it to auto hide.

use std::{ffi::OsStr, os::windows::ffi::OsStrExt, ptr::null_mut};
use windows_sys::Win32::System::LibraryLoader::GetModuleHandleW;
use windows_sys::Win32::UI::{Shell::*, WindowsAndMessaging::*};
use windows_sys::Win32::Graphics::Gdi::UpdateWindow;
use windows_sys::Win32::Foundation::*;
use std::mem::zeroed;

const WM_APPBAR: u32 = WM_USER + 1;

pub fn to_wstring(str: &str) -> Vec<u16> { OsStr::new(str)
    .encode_wide().chain(Some(0).into_iter()).collect() }

unsafe extern "system" fn wnd_proc(hwnd: HWND, msg: u32, wp: WPARAM, lp: LPARAM) -> LRESULT {
    match msg {
        WM_APPBAR => {
            if lp == ABN_POSCHANGED as isize ||
               lp == ABN_STATECHANGE as isize
            { update_appbar(hwnd); } 0
        },
        WM_DESTROY => {
            let mut abd: APPBARDATA = std::mem::zeroed();
            abd.cbSize = std::mem::size_of::<APPBARDATA>() as u32;
            abd.hWnd = hwnd; abd.uEdge = ABE_TOP;
            abd.rc = RECT { left: 0, top: 0, right: GetSystemMetrics(SM_CXSCREEN), bottom: 30 };
            abd.lParam = ABS_ALWAYSONTOP as isize;
            abd.uCallbackMessage = WM_APPBAR;
            SHAppBarMessage(ABM_REMOVE, &mut abd);
            PostQuitMessage(0);
            0
        },
        _ => DefWindowProcW(hwnd, msg, wp, lp)
    }
}

fn main() {
    unsafe {
        RegisterClassW(&WNDCLASSW {
            lpszClassName: to_wstring("utilbar_main_toolbar").as_ptr(),
            hCursor: LoadCursorW(null_mut(), IDC_ARROW),
            hInstance: GetModuleHandleW(null_mut()),
            cbClsExtra: 0, cbWndExtra: 0,
            lpfnWndProc: Some(wnd_proc),
            hbrBackground: null_mut(),
            lpszMenuName: null_mut(),
            hIcon: null_mut(),
            style: 0,
        });
        let hwnd = CreateWindowExW(
            WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE,
            to_wstring("utilbar_main_toolbar").as_ptr(),
            to_wstring("").as_ptr(),
            WS_POPUP,
            0,
            0,
            GetSystemMetrics(SM_CXSCREEN),
            30,
            null_mut(),
            null_mut(),
            GetModuleHandleW(null_mut()),
            null_mut()
        );
        ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); update_appbar(hwnd);

        let taskbar_hwnd = FindWindowW(to_wstring("Shell_TrayWnd").as_ptr(), null_mut());
        let mut abd: APPBARDATA = std::mem::zeroed(); abd.lParam = ABS_AUTOHIDE as isize;
        abd.cbSize = size_of::<APPBARDATA>() as u32; abd.hWnd = taskbar_hwnd;
        SHAppBarMessage(ABM_SETSTATE, &mut abd);

        let mut msg: MSG = zeroed();
        while GetMessageW(&mut msg, hwnd, 0, 0) > 0
        { TranslateMessage(&msg); DispatchMessageW(&msg); }
    }
}

unsafe fn update_appbar(hwnd: HWND) {
    let mut abd: APPBARDATA = std::mem::zeroed();
    abd.cbSize = std::mem::size_of::<APPBARDATA>() as u32;
    abd.hWnd = hwnd; abd.uEdge = ABE_TOP;
    abd.rc = RECT { left: 0, top: 0, right: GetSystemMetrics(SM_CXSCREEN), bottom: 30 };
    abd.lParam = ABS_ALWAYSONTOP as isize;
    abd.uCallbackMessage = WM_APPBAR;
    SHAppBarMessage(ABM_NEW, &mut abd);
    SHAppBarMessage(ABM_SETPOS, &mut abd);
    SHAppBarMessage(ABM_SETSTATE, &mut abd);
    SetWindowPos(hwnd, null_mut(), 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}

Even in the settings app if I toggle "Automatically hide taskbar" it reappears.

Why does this happen? How can I fix it?

The full source code is here on github: https://github.com/barnabasd/utilbar

Upvotes: 0

Views: 56

Answers (0)

Related Questions