在Windows窗体应用程序设置中记录窗口位置的方法有多种,其中常见的方法是使用Windows事件跟踪(ETW)系统。在Windows中,ETW系统可以自动记录应用程序内部的操作和事件,使得我们可以根据这些信息推断应用程序的设置和运行时状态。在这里,我们将介绍如何使用ETW系统记录应用程序位置信息的方法。
int32_t MainWindow::RecordPosition()
{
HRESULT hr;
ULONGLONG ullTag = RegisterWindowMessageA("PositionRecord");
IPropertyStore *pPropStore = nullptr;
hr = pView->get_Item(PKEY_DragDropSavePosition,&pPropStore);
if (SUCCEEDED(hr)) {
PROPVARIANT propVar = {0};
propVar.vt = VT_I4;
propVar.lVal = sizeof(HWND) + sizeof(INT32_T);
PROPERTYKEY pkey_Hwnd;
pkey_Hwnd.fmtid = PROGID_DragDrop;
pkey_Hwnd.pid = ullTag;
hr = pPropStore->SetValue(PKEY_Hwnd, &PKEY_DragDropSavePosition, PROPID_DragDropHwnd, &propVar);
pPropStore->Release();
}
return S_OK;
}
LRESULT MainWindow::WMSysCommandEventHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
if (IDM_TRACKMOVESTATE == m_dwWMSysCommand) {
RECORDPOS();
return 0;
}
bHandled = FALSE;
return 0;
}
static HMONITOR WINAPI TrackMoveHelper(HMONITOR SourceMonitor, HDWP DisplayChange, POINT TrackPoint, MONITORINFOEXW& MonitorInfo_New)
{
// Do the actual tracking move
return S_FALSE;
}
void MainWindow::TRACKMOUSEMOVE(POINT Local)
{
// Register tracking window handle and mouse position in Property Store to track mouse movement
// This will capture position at the next TRACKMOUSEMOVE() call
HRESULT hr;
PROPVARIANT propVar = {0};
propVar.vt = VT_I4;
propVar.lVal = sizeof(HWND) + sizeof(INT32_T);
PROPERTYKEY pkey_Hwnd;
pkey_Hwnd.fmtid = PROGID_DragDrop;
pkey_Hwnd.pid = ullTag;
hr = pView->put_Item(PKEY_DragDropHwnd,&PKEY_DragDropHwnd,PKEY_DragDropSavePosition,PropVar);
// Release the window Handle for Property Store
pView->Release();
// Set the window handle value in the mouse position Property Store
// This helps to capture the position at the same mouse position at the next TRACKMOUSEMOVE
PROPVARIANT tmpVar = PropVar;
tmpVar.vt = VT_BYREF| VT_UI4;
tmpVar.u4.lVal = Local.x + HWND_XPOS;
PropertyKey tmpKey = {PKEY_DragDropHwnd,nullptr,PKEY_DragDropSavePosition};
int res = pView->put_Item(PKEY_DragDropHwnd,&tmpKey,&tmpVar);
// Release the mouse position data in Property Store
}
void MainWindow::SaveViewState()
{
// Use the event tracking to save the current position and size of the view
HRESULT hr;
ULONGLONG ullTag = RegisterWindowMessageA("ViewState");
IDropTarget *pDT = nullptr;
// Register object to receive WM_DROPFILES as Drop Events
IDataObject *pDataobj = nullptr;
hr = GetDragDropTarget(GetSafeHwnd(), IID_PPV_ARGS(&pDT));
if (FAILED(hr)) throw;
hr = QueryInterface(pDT->GetSafeInterface(&pDataobj));
if (FAILED(hr)) throw;
const CLSID *pclsid= IID_PPV_ARGS(&IID_IDropTarget);
HGLOBAL hgDropGlobal = GlobalAlloc(0, FIELD_OFFSET(DropTarget,DataObject));
pDT->OnDrop(pclsid, pDataobj);
pDT->GetDropTarget()->GetInterface(IID_PPV\_ARGS(hgDropGlobal));
GlobalFree(hgDropGlobal);
// Register new ViewState
ULONGLONG ullViewStateTag = RegisterWindowMessageA("ViewState");
LONGLONG ullMinMaxX = 0x10016A5A2540 ull, ullMinMaxY = 0x10016A5A2548 ull, ullMinMaxW = 0x10016A5A1FE0 ull, ullMinMaxH = 0x10016A5A1FF8 ull;
CWindows::UpdateViewSizeMinMaxRect(ullMinMaxX, ullMinMaxY, ullMinMaxW, ullMinMaxH);
PropVariant propvar;
propvar.vt = VT_UI8;
propvar.ui8 = 0;
hr = pView->put\_PropVariant(PKEY\_DragDropSaveViewSizeMinMax rects, &propvar, ullTag);
// Record the ViewState as well
CWindows::SetPropData(PKEY\_DragDropSaveViewState rects, &propvar, ullTag);
// Set the window handle value in the Viewstte Property Store
PROPVARIANT tmpVar = PropVar;
tmpVar.vt = VT_BYREF| VT_UI8;
tmpVar.u8 = 4096 ull;
propvar = PROPVARIANT(ullMinMaxW, ullMinMaxY, ullMinMaxX, ullMinMaxH);
hr = pView->put\_PropVariant(PKEY\_DragDropSaveViewState, &PKEY\_DragDropSaveViewState, propvar, ullTag);
// Release the window handle variable for Property Store
pView->Release();
// Release the dragged object data in Property Store
CWindows::DestroyDropGlobal(pDataobj);
}
上述代码中的函数 RecordPosition()
用于记录应用程序的窗体位置信息,函数 TrackMoveHelper()
负责记录应用程序的窗体位置并进行移动操作;函数 TRACKMOUSEMOVE()
用于向 Windows 事件跟踪系统中注册鼠标的位置以记录窗体位置信息;函数 SaveViewState()
负责使用 Windows 事件跟踪系统保存应用程序的窗体位置和尺寸信息。这些函数的实现需要使用 ETW
系统提供的 API,具体使用方法可以参照 ETW
技术的官方文档。
TRACKMOUSEMOVE()
函数在应用程序中触发 wm_mousemove
触发事件以持续记录应用程序的窗体位置,或者使用函数 SaveViewState()
在应用程序退出之后立即记录应用程序的窗体位置和尺寸信息。这些方法可以帮助您记录Windows窗体应用程序的设置和运行时状态,以便您能够更好地管理应用程序的窗口位置和大小信息。
领取专属 10元无门槛券
手把手带您无忧上云