Skip to content

Commit

Permalink
Merge pull request #9 from hatelamers/feature/6_multiscreen_support
Browse files Browse the repository at this point in the history
#6 added support for multi-monitor taskbar
  • Loading branch information
hatelamers authored Nov 15, 2024
2 parents 1798176 + 368043a commit ce19388
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 74 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

/build
**/LocalBuild.*
/test/data

# User-specific files
*.rsuser
Expand Down
2 changes: 1 addition & 1 deletion buildenv/Product.cmake
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
set(PRODUCT_VERSION_MAJOR 0)
set(PRODUCT_VERSION_MINOR 1)
set(PRODUCT_VERSION_PATCH 0)
set(PRODUCT_VERSION_PATCH 1)
set(PRODUCT_NAME WinPinMenu)
set(PRODUCT_VERSION ${PRODUCT_VERSION_MAJOR}.${PRODUCT_VERSION_MINOR}.${PRODUCT_VERSION_PATCH}.${BUILD_NUMBER})
set(PRODUCT_VENDOR "diVISION")
Expand Down
2 changes: 1 addition & 1 deletion buildenv/buildnumber.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24
26
1 change: 1 addition & 0 deletions src/app/AboutDlg.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class CAboutDlg
BEGIN_MSG_MAP(CAboutDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
COMMAND_ID_HANDLER(IDRETRY, OnCloseCmd)
COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
END_MSG_MAP()

Expand Down
58 changes: 36 additions & 22 deletions src/app/MainFrm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,14 @@ LRESULT CMainFrame::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCt
LRESULT CMainFrame::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
CAboutDlg dlg;
dlg.DoModal();
TriggerActionPopup();
if (IDRETRY == dlg.DoModal())
{
TriggerActionPopup();
}
else
{
PostMessage(WM_CLOSE);
}
return 0;
}

Expand Down Expand Up @@ -228,51 +234,59 @@ INT CMainFrame::TriggerActionPopup()

POINT CMainFrame::CalculatePopupPosision()
{
POINT result{ 0,0 };
ATLTRACE(__FUNCTION__ _T(" START\n"));
POINT result{ -1,-1 };
POINT cursorPos{ 0,0 };
if (::GetCursorPos(&cursorPos))
{
result.x = cursorPos.x;
result.y = cursorPos.y;
}

CTaskbarAutomation tba;
tba.ForEveryButton([this,&result](const CComPtr<IUIAutomationElement>& button, int)
auto hrButtons = tba.ForEveryButton([this,&result,&cursorPos](const CComPtr<IUIAutomationElement>& button, int /*tbIndex*/, int /*btnIndex*/)
{
CComBSTR bstrName;
auto hr = button->get_CurrentName(&bstrName);
//ATLTRACE(_T("Button[%d].Name=%s\n"), index, (LPCOLESTR)bstrName);
if (SUCCEEDED(hr))
RECT rc{ 0,0,0,0 };
if (SUCCEEDED(button->get_CachedBoundingRectangle(&rc)))
{
CString strName(bstrName);
CString strTitle;
GetWindowText(strTitle);
if (0 == strName.Find(strTitle))
auto hasFocus = FALSE;
button->get_CurrentHasKeyboardFocus(&hasFocus);
if (!hasFocus)
{
RECT rc{ 0,0,0,0 };
if (SUCCEEDED(button->get_CurrentBoundingRectangle(&rc)))
{
result.x = rc.left;
result.y = rc.top;
}
hasFocus = (cursorPos.x >= rc.left && cursorPos.x <= rc.right && cursorPos.y >= rc.top && cursorPos.y <= rc.bottom);
}
ATLTRACE(__FUNCTION__ _T(" taskbar button at x=%d y=%d, hasFocus=%d\n"), rc.left, rc.top, hasFocus);
if (hasFocus)
{
result.x = 10 > rc.left ? rc.right : rc.left;
result.y = 10 > rc.top ? rc.bottom + 2 : rc.top - 2;
return false;
}
}
return true;
});

if (0 == result.x && 0 == result.y)
if (S_FALSE != hrButtons)
{
if (!::GetCursorPos(&result))
if (-1 == result.x)
{
result.x = 100;
result.y = -1;
}

auto hTaskBar = ::FindWindow(_T("Shell_TrayWnd"), NULL);
if (hTaskBar)
{
RECT rc{ 0,0,0,0 };
if (::GetWindowRect(hTaskBar, &rc) &&
(0 > result.y
|| (result.x >= rc.left && result.x <= rc.right && result.y >= rc.top && result.y <= rc.bottom)))
|| (cursorPos.x >= rc.left && cursorPos.x <= rc.right && cursorPos.y >= rc.top && cursorPos.y <= rc.bottom)))
{
result.y = rc.top;
result.y = 10 > rc.top ? rc.bottom + 2 : rc.top - 2;
}
}
}
ATLTRACE(__FUNCTION__ _T(" END\n"));
return result;
}

Expand Down
9 changes: 5 additions & 4 deletions src/app/WinPinMenu.rc
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,15 @@ END
// Dialog
//

IDD_ABOUTBOX DIALOGEX 0, 0, 242, 121
IDD_ABOUTBOX DIALOGEX 0, 0, 242, 134
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTERMOUSE | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About"
FONT 9, "Segoe UI", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "OK",IDOK,185,100,50,14
DEFPUSHBUTTON "O&K",IDOK,185,113,50,14
PUSHBUTTON "&Back To Menu",IDRETRY,131,113,50,14
ICON IDR_MAINFRAME,IDC_STATIC,12,15,20,20
GROUPBOX "",IDC_STATIC,7,7,228,107
GROUPBOX "",IDC_STATIC,7,7,228,120
LTEXT "Product Name",IDC_TXT_PRODUCTNAME,41,15,125,18
RTEXT "License",IDC_LNK_LICENSE,172,15,57,8
RTEXT "Company Name",IDC_TXT_COMPANYNAME,172,26,57,8
Expand Down Expand Up @@ -129,7 +130,7 @@ BEGIN
VERTGUIDE, 172
VERTGUIDE, 229
TOPMARGIN, 7
BOTTOMMARGIN, 114
BOTTOMMARGIN, 127
HORZGUIDE, 15
HORZGUIDE, 39
HORZGUIDE, 68
Expand Down
14 changes: 7 additions & 7 deletions src/app/productmeta.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@

#define PRODUCT_VERSION_MAJOR 0
#define PRODUCT_VERSION_MINOR 1
#define PRODUCT_VERSION_PATCH 0
#define PRODUCT_VERSION_TWEAK 24
#define PRODUCT_VERSION_PATCH 1
#define PRODUCT_VERSION_TWEAK 26
#define PRODUCT_NAME _T("WinPinMenu\0")
#define PRODUCT_DESCRIPTION _T("diVISION Pinnable Taskbar Menu For Windows\0")
#define PRODUCT_HOMEPAGE_URL _T("https://winpinmenu.sourceforge.net\0")
#define PRODUCT_HOMEPAGE_URL _T("https://github.com/hatelamers/WinPinMenu\0")
#define PRODUCT_VENDOR _T("diVISION\0")
#define PRODUCT_LICENSE _T("GNU/GPL\0")
#define PRODUCT_LICENSE_URL _T("https://www.gnu.org/licenses/gpl-3.0.en.html\0")
#define PRODUCT_COPYRIGHT _T("© 2024, some rights reserved\0")

#define PRODUCT_VERSION 0,1,0
#define PRODUCT_VERSION_S _T("0.1.0\0")
#define PRODUCT_VERSION 0,1,1
#define PRODUCT_VERSION_S _T("0.1.1\0")

#define FILE_NAME _T("WinPinMenu\0")
#define FILE_DESCRIPTION _T("diVISION Pinnable Taskbar Menu For Windows\0")

#define FILE_VERSION 0,1,0,24
#define FILE_VERSION_S _T("0.1.0.24\0")
#define FILE_VERSION 0,1,1,26
#define FILE_VERSION_S _T("0.1.1.26\0")
3 changes: 2 additions & 1 deletion src/app/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define IDC_TXT_PRODUCTVERSION 1005
#define IDC_TXT_FILEVERSION 1006
#define IDC_TXT_LEGALCOPYRIGHT 1007
#define IDC_BUTTON1 1008
#define IDS_EMPTY_FOLDER 32772
#define IDS_INVALID_SOURCE 32773
#define ID_FILE_NOACTIONSOURCE 32775
Expand All @@ -25,7 +26,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 203
#define _APS_NEXT_COMMAND_VALUE 32776
#define _APS_NEXT_CONTROL_VALUE 1008
#define _APS_NEXT_CONTROL_VALUE 1009
#define _APS_NEXT_SYMED_VALUE 102
#endif
#endif
100 changes: 62 additions & 38 deletions src/app/taskbarautomation.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class CTaskbarAutomation

bool IsReady() const noexcept
{
return m_pFirstElement && m_pSearchConditionButton;
return m_pTaskbars && m_pSearchConditionButton;
}

template<typename TFunc>
Expand All @@ -27,81 +27,105 @@ class CTaskbarAutomation
ATLTRACE2(_T("CTaskbarAutomation hasn't been initialed\n"));
return E_FAIL;
}
CComPtr<IUIAutomationElementArray> pTaskbarButtonElements;
auto hr = m_pFirstElement->FindAll(TreeScope_Descendants, m_pSearchConditionButton, &pTaskbarButtonElements);
if (SUCCEEDED(hr))

auto tbCount = 0;
auto hr = m_pTaskbars->get_Length(&tbCount);
ATLTRACE(__FUNCTION__ _T(" %d taskbars\n"), tbCount);
for (auto i = 0; SUCCEEDED(hr) && i < tbCount; i++)
{
auto count = 0;
hr = pTaskbarButtonElements->get_Length(&count);
for (auto i = 0; SUCCEEDED(hr) && i < count; i++)
CComPtr<IUIAutomationElement> pTaskbar;
hr = m_pTaskbars->GetElement(i, &pTaskbar);
if (SUCCEEDED(hr))
{
CComPtr<IUIAutomationElement> pButton;
hr = pTaskbarButtonElements->GetElement(i, &pButton);
if (SUCCEEDED(hr) && !itemReceiver(pButton, i))
CComPtr<IUIAutomationElementArray> pTaskbarButtonElements;
hr = pTaskbar->FindAllBuildCache(TreeScope_Descendants, m_pSearchConditionButton, m_pCacheRequestButton, &pTaskbarButtonElements);
if (SUCCEEDED(hr))
{
hr = S_FALSE;
break;
auto btnCount = 0;
hr = pTaskbarButtonElements->get_Length(&btnCount);
for (auto j = 0; SUCCEEDED(hr) && j < btnCount; j++)
{
CComPtr<IUIAutomationElement> pButton;
hr = pTaskbarButtonElements->GetElement(j, &pButton);
if (SUCCEEDED(hr) && !itemReceiver(pButton, i, j))
{
hr = S_FALSE;
break;
}
}
}

}
}

return hr;
}

protected:
bool Initialize()
{
if (m_pFirstElement && m_pSearchConditionButton)
ATLTRACE(__FUNCTION__ _T(" START\n"));
if (m_pTaskbars && m_pSearchConditionButton)
return true;

auto hr = S_OK;
if (!m_pAutomation)
{
hr = m_pAutomation.CoCreateInstance(__uuidof(CUIAutomation), NULL, CLSCTX_INPROC_SERVER);
//HRESULT hr = CoCreateInstance(__uuidof(CUIAutomation), NULL, CLSCTX_INPROC_SERVER, __uuidof(IUIAutomation), (void**)&m_pAutomation);
if (FAILED(hr)) return false;
}

CComPtr<IUIAutomationElement> pRootElement;
hr = m_pAutomation->GetRootElement(&pRootElement);
if (FAILED(hr)) return false;

CComPtr<IUIAutomationCondition> pPrimTaskbarCondition;
hr = m_pAutomation->CreatePropertyCondition(UIA_ClassNamePropertyId, CComVariant(L"Shell_TrayWnd"), &pPrimTaskbarCondition);
if (FAILED(hr)) return false;

CComPtr<IUIAutomationCondition> pSecondTaskbarCondition;
hr = m_pAutomation->CreatePropertyCondition(UIA_ClassNamePropertyId, CComVariant(L"Shell_SecondaryTrayWnd"), &pSecondTaskbarCondition);
if (FAILED(hr)) return false;

CComPtr<IUIAutomationCondition> pTaskbarCondition;
hr = m_pAutomation->CreatePropertyCondition(UIA_ClassNamePropertyId, CComVariant(L"MSTaskListWClass"), &pTaskbarCondition);
if (SUCCEEDED(hr))
{
hr = pRootElement->FindFirst(TreeScope_Descendants, pTaskbarCondition, &m_pFirstElement);
if (SUCCEEDED(hr) && m_pFirstElement)
{
hr = m_pAutomation->CreatePropertyCondition(UIA_ControlTypePropertyId, CComVariant(UIA_ButtonControlTypeId), &m_pSearchConditionButton);
if (FAILED(hr)) return false;
}
}
hr = m_pAutomation->CreateOrCondition(pPrimTaskbarCondition, pSecondTaskbarCondition, &pTaskbarCondition);
if (FAILED(hr)) return false;

if (!m_pFirstElement)
{
if (pTaskbarCondition)
{
pTaskbarCondition.Release();
}
hr = m_pAutomation->CreatePropertyCondition(UIA_ClassNamePropertyId, CComVariant(L"Shell_TrayWnd"), &pTaskbarCondition);
if (FAILED(hr)) return false;
hr = pRootElement->FindAll(TreeScope_Children, pTaskbarCondition, &m_pTaskbars);
if (FAILED(hr) || !m_pTaskbars) return false;

hr = pRootElement->FindFirst(TreeScope_Children, pTaskbarCondition, &m_pFirstElement);
if (FAILED(hr) || !m_pFirstElement) return false;
//CComPtr<IUIAutomationCondition> pTaskListCondition;
//hr = m_pAutomation->CreatePropertyCondition(UIA_ClassNamePropertyId, CComVariant(L"MSTaskListWClass"), &pTaskListCondition);
//if (FAILED(hr)) return false;


hr = m_pAutomation->CreatePropertyCondition(UIA_ClassNamePropertyId, CComVariant(L"Taskbar.TaskListButtonAutomationPeer"), &m_pSearchConditionButton);
if (FAILED(hr)) return false;
}
CComPtr<IUIAutomationCondition> pSearchConditionUXButton;
hr = m_pAutomation->CreatePropertyCondition(UIA_ClassNamePropertyId, CComVariant(L"Taskbar.TaskListButtonAutomationPeer"), &pSearchConditionUXButton);
if (FAILED(hr)) return false;

CComPtr<IUIAutomationCondition> pSearchConditionButton;
hr = m_pAutomation->CreatePropertyCondition(UIA_ControlTypePropertyId, CComVariant(UIA_ButtonControlTypeId), &pSearchConditionButton);
if (FAILED(hr)) return false;

hr = m_pAutomation->CreateOrCondition(pSearchConditionButton, pSearchConditionUXButton, &m_pSearchConditionButton);
if (FAILED(hr)) return false;

hr = m_pAutomation->CreateCacheRequest(&m_pCacheRequestButton);
if (FAILED(hr)) return false;

hr = m_pCacheRequestButton->AddProperty(UIA_BoundingRectanglePropertyId);
if (FAILED(hr)) return false;

ATLTRACE(__FUNCTION__ _T(" END\n"));
return true;

}

protected:

CComPtr<IUIAutomation> m_pAutomation;
CComPtr<IUIAutomationElement> m_pFirstElement;
CComPtr<IUIAutomationElementArray> m_pTaskbars;
CComPtr<IUIAutomationCondition> m_pSearchConditionButton;
CComPtr<IUIAutomationCacheRequest> m_pCacheRequestButton;

};

0 comments on commit ce19388

Please sign in to comment.