rename dir 1
This commit is contained in:
677
PROGMGR2/group.c
Normal file
677
PROGMGR2/group.c
Normal file
@@ -0,0 +1,677 @@
|
||||
/* * * * * * * *\
|
||||
GROUP.C -
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Group window and program group/item functions.
|
||||
LICENSE INFORMATION -
|
||||
MIT License, see LICENSE.txt in the root folder
|
||||
\* * * * * * * */
|
||||
|
||||
/* Headers */
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <CommCtrl.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shellapi.h>
|
||||
#include <strsafe.h>
|
||||
#include <uxtheme.h>
|
||||
#include "progmgr.h"
|
||||
#include "group.h"
|
||||
#include "resource.h"
|
||||
#include "registry.h"
|
||||
|
||||
/* Variables */
|
||||
WNDCLASSEX wcGrp;
|
||||
WCHAR szGrpClass[16];
|
||||
HWND hWndMDIClient = NULL;
|
||||
HWND hWndFoundGroup = NULL;
|
||||
|
||||
/* Functions */
|
||||
|
||||
/* * * *\
|
||||
InitializeGroups -
|
||||
Create the MDI Client window and initialize
|
||||
the group window class.
|
||||
RETURNS -
|
||||
TRUE if groups are successfully created.
|
||||
FALSE if otherwise.
|
||||
\* * * */
|
||||
BOOL InitializeGroups(VOID)
|
||||
{
|
||||
CLIENTCREATESTRUCT ccs = { 0 };
|
||||
WNDCLASSEX wce = { 0 };
|
||||
RECT rcFrame;
|
||||
|
||||
// Create the MDI Client Window
|
||||
ccs.hWindowMenu = GetSubMenu(GetMenu(g_hWndProgMgr), 2);
|
||||
ccs.idFirstChild = IDM_WINDOW_CHILDSTART;
|
||||
|
||||
GetClientRect(g_hWndProgMgr, &rcFrame);
|
||||
|
||||
if ((hWndMDIClient = CreateWindowEx(WS_EX_COMPOSITED,
|
||||
TEXT("MDIClient"), NULL, WS_CLIPCHILDREN | WS_CHILD |
|
||||
WS_VSCROLL | WS_HSCROLL | WS_VISIBLE,
|
||||
rcFrame.left, rcFrame.top, rcFrame.right, rcFrame.bottom,
|
||||
g_hWndProgMgr, (HMENU)1, g_hAppInstance, (LPWSTR)&ccs)) == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Load the group class string
|
||||
LoadString(g_hAppInstance, IDS_GRPCLASS,
|
||||
szGrpClass, ARRAYSIZE(szGrpClass));
|
||||
|
||||
// Register the group window class
|
||||
wce.cbSize = sizeof(WNDCLASSEX);
|
||||
wce.style = CS_DBLCLKS;
|
||||
wce.lpfnWndProc = GroupWndProc;
|
||||
wce.cbClsExtra = 0;
|
||||
wce.cbWndExtra = 0;
|
||||
wce.hInstance = g_hAppInstance;
|
||||
wce.hIcon = g_hGroupIcon = LoadImage(g_hAppInstance,
|
||||
MAKEINTRESOURCE(IDI_PROGGRP), IMAGE_ICON,
|
||||
0, 0, LR_DEFAULTSIZE | LR_SHARED);
|
||||
wce.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||
wce.lpszMenuName = NULL;
|
||||
wce.lpszClassName = szGrpClass;
|
||||
|
||||
if (!RegisterClassEx(&wce))
|
||||
return FALSE;
|
||||
|
||||
// Now we can create the groups
|
||||
if(LoadConfig(FALSE, FALSE, TRUE) != RCE_SUCCESS)
|
||||
return FALSE;
|
||||
|
||||
// TODO: if loading groups fails, throw an error
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
CreateGroup -
|
||||
Create an MDI window from a group structure
|
||||
RETURNS -
|
||||
Handle to the new group window
|
||||
or NULL on failure
|
||||
\* * * */
|
||||
HWND CreateGroup(_In_ PGROUP pg)
|
||||
{
|
||||
MDICREATESTRUCT mcs = { NULL };
|
||||
PGROUP pGroup = NULL;
|
||||
HICON hIconLarge = NULL;
|
||||
HICON hIconSmall = NULL;
|
||||
HICON hIconTemp = NULL;
|
||||
HWND hWndGroup = NULL;
|
||||
HIMAGELIST hImageList = NULL;
|
||||
HWND hWndListView = NULL;
|
||||
RECT rcGroupWindow = { 0 };
|
||||
LVCOLUMN lvc = { 0 };
|
||||
|
||||
if (pg == NULL)
|
||||
return NULL;
|
||||
|
||||
// error checking, if we get trash don't try to
|
||||
// make a group out of it
|
||||
// TODO: if a group is garbled, throw an error
|
||||
// and ask the user if they want to delete it!
|
||||
if (pg->dwSignature != GRP_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
// allocate memory for a new group
|
||||
pGroup = (PGROUP)malloc(CalculateGroupMemory(pg, 1, 0));
|
||||
if (pGroup == NULL)
|
||||
return NULL;
|
||||
|
||||
// clean up the memory if it's valid
|
||||
ZeroMemory(pGroup, sizeof(*pGroup));
|
||||
|
||||
// copy over the group structure
|
||||
*pGroup = *pg;
|
||||
|
||||
// TODO: get group minimized/maximized flags
|
||||
|
||||
mcs.szClass = szGrpClass;
|
||||
mcs.szTitle = pg->szName;
|
||||
mcs.hOwner = g_hAppInstance;
|
||||
if ((pg->rcGroup.left == CW_USEDEFAULT) & (pg->rcGroup.right == CW_USEDEFAULT))
|
||||
{
|
||||
mcs.x = mcs.y = mcs.cx = mcs.cy = CW_USEDEFAULT;
|
||||
}
|
||||
mcs.style = WS_VISIBLE | WS_THICKFRAME | WS_CAPTION | WS_BORDER | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
|
||||
// TODO: should I pass the pointer to the group through here
|
||||
// or is it better and easier to just do it with GWLP_USERDATA?
|
||||
mcs.lParam = (LPARAM)NULL;
|
||||
|
||||
if ((hWndGroup = (HWND)SendMessage(hWndMDIClient, WM_MDICREATE, 0,
|
||||
(LPARAM)(LPTSTR)&mcs)) == NULL)
|
||||
return NULL;
|
||||
|
||||
// Associate the group structure pointer to the group window
|
||||
SetWindowLongPtr(hWndGroup, GWLP_USERDATA, (LONG_PTR)pGroup);
|
||||
|
||||
// Resize the group
|
||||
if (pg->wp.length == sizeof(WINDOWPLACEMENT))
|
||||
SetWindowPlacement(hWndGroup, &pg->wp);
|
||||
|
||||
// Load the group icon
|
||||
if (ExtractIconEx(pg->szIconPath, pg->iIconIndex, &hIconLarge, &hIconSmall, 1))
|
||||
{
|
||||
if (hIconTemp = (HICON)SendMessage(hWndGroup, WM_SETICON,
|
||||
ICON_SMALL, (LPARAM)hIconSmall))
|
||||
DestroyIcon(hIconTemp);
|
||||
if (hIconTemp = (HICON)SendMessage(hWndGroup, WM_SETICON,
|
||||
ICON_BIG, (LPARAM)hIconLarge))
|
||||
DestroyIcon(hIconTemp);
|
||||
}
|
||||
|
||||
// Get the group window rect
|
||||
GetClientRect(hWndGroup, &rcGroupWindow);
|
||||
|
||||
// Create the group window ListView control
|
||||
if ((hWndListView = CreateWindowEx(WS_EX_LEFT, WC_LISTVIEW,
|
||||
TEXT("ListView"),
|
||||
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
|
||||
LVS_ICON | LVS_SINGLESEL | LVS_AUTOARRANGE,
|
||||
mcs.x, mcs.y, mcs.cx, mcs.cy,
|
||||
hWndGroup, NULL, g_hAppInstance, NULL)) == NULL)
|
||||
return NULL;
|
||||
|
||||
// ((LVS_AUTOARRANGE & bAutoArrange) * LVS_AUTOARRANGE)
|
||||
|
||||
// Resize it to fit the window
|
||||
SetWindowPos(hWndListView, NULL,
|
||||
rcGroupWindow.left, rcGroupWindow.top,
|
||||
rcGroupWindow.right - rcGroupWindow.left,
|
||||
rcGroupWindow.bottom - rcGroupWindow.top, SWP_NOZORDER);
|
||||
|
||||
// Add the explorer style because it looks good
|
||||
SetWindowTheme(hWndListView, TEXT("Explorer"), NULL);
|
||||
|
||||
// Get this bad boy an image list
|
||||
// TODO: if cxicon/cyicon change make sure we handle that
|
||||
// don't require a program restart, DPI!!!
|
||||
hImageList = ImageList_Create(GetSystemMetrics(SM_CXICON),
|
||||
GetSystemMetrics(SM_CYICON), ILC_COLOR32, 0, 1);
|
||||
ListView_SetImageList(hWndListView, hImageList, LVSIL_NORMAL);
|
||||
|
||||
// since the list is viewing we can load items if applicable
|
||||
if (pGroup->cItemArray > 0)
|
||||
LoadItems(hWndGroup);
|
||||
|
||||
// TODO: make sure the groups delete their icons upon destruction!
|
||||
// AND IMAGE LIST!!!!!!!!? i think it's nuked w/ listview though
|
||||
return hWndGroup;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
RemoveGroup -
|
||||
Removes and cleans up a group window
|
||||
RETURNS -
|
||||
TRUE if cleanup is successful,
|
||||
FALSE otherwise.
|
||||
\* * * */
|
||||
BOOL RemoveGroup(_In_ HWND hWndGroup, _In_ BOOL bEliminate)
|
||||
{
|
||||
PGROUP pGroup = NULL;
|
||||
BOOL bReturn = TRUE;
|
||||
|
||||
// TODO: do i have to delete the titlebar icons?
|
||||
|
||||
if (bEliminate == TRUE)
|
||||
{
|
||||
// TODO: remove group from registry
|
||||
// if successful blah blah blah
|
||||
bEliminate = TRUE;
|
||||
}
|
||||
|
||||
// get the group struct pointer
|
||||
if ((pGroup = (PGROUP)GetWindowLongPtr(hWndGroup, GWLP_USERDATA)) == NULL)
|
||||
bReturn = FALSE;
|
||||
else
|
||||
free(pGroup);
|
||||
|
||||
// close the group window
|
||||
SendMessage(hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndGroup, 0);
|
||||
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
CreateItem -
|
||||
Creates a new program item
|
||||
RETURNS -
|
||||
Pointer to the item if successful
|
||||
NULL otherwise
|
||||
\* * * */
|
||||
PITEM CreateItem(_In_ HWND hWndGroup, _In_ PITEM pi)
|
||||
{
|
||||
PGROUP pGroup = NULL;
|
||||
PGROUP pNewGroup = NULL;
|
||||
PITEM pItem = NULL;
|
||||
HWND hWndListView = NULL;
|
||||
HIMAGELIST hImageList = NULL;
|
||||
HICON hIcon = NULL;
|
||||
LVITEM lvi = { 0 };
|
||||
|
||||
// we actually just want the group pointer lol
|
||||
pGroup = (PGROUP)GetWindowLongPtr(hWndGroup, GWLP_USERDATA);
|
||||
|
||||
// return NULL if we can't get to the group or item
|
||||
if (hWndGroup == NULL)
|
||||
return NULL;
|
||||
if (pGroup == NULL)
|
||||
return NULL;
|
||||
if (pi == NULL)
|
||||
return NULL;
|
||||
|
||||
// get the listview window
|
||||
hWndListView = FindWindowEx(hWndGroup, NULL, WC_LISTVIEW, NULL);
|
||||
if (hWndListView == NULL)
|
||||
return NULL;
|
||||
|
||||
// if we reallocate memory then send the new pointer in
|
||||
pNewGroup = realloc(pGroup, CalculateGroupMemory(pGroup, 1, 0));
|
||||
if (pNewGroup != NULL)
|
||||
{
|
||||
pGroup = pNewGroup;
|
||||
SetWindowLongPtr(hWndGroup, GWLP_USERDATA, (LONG_PTR)pGroup);
|
||||
}
|
||||
|
||||
// add the item
|
||||
pItem = pGroup->pItemArray + pGroup->cItemArray;
|
||||
*pItem = *pi;
|
||||
|
||||
// increment the item counter
|
||||
pGroup->cItemArray++;
|
||||
|
||||
// then get the pointer to the group's image list
|
||||
hImageList = ListView_GetImageList(hWndListView, LVSIL_NORMAL);
|
||||
|
||||
// extract that icon son!!
|
||||
hIcon = ExtractIcon(g_hAppInstance, (LPWSTR)pItem->szIconPath, pItem->iIconIndex);
|
||||
|
||||
// populate the listview with the relevant information
|
||||
lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
|
||||
lvi.iItem = pGroup->cItemArray;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.pszText = pItem->szName;
|
||||
lvi.cchTextMax = ARRAYSIZE(pItem->szName);
|
||||
lvi.iImage = ImageList_AddIcon(hImageList, hIcon);
|
||||
lvi.lParam = (LPARAM)pItem;
|
||||
|
||||
// copy that bad boy into the listview
|
||||
ListView_InsertItem(hWndListView, &lvi);
|
||||
|
||||
// get that hicon outta here
|
||||
DestroyIcon(hIcon);
|
||||
|
||||
// this is all terrible i'm gonna rewrite this whole file
|
||||
// why is the listview even touched here just... omg...
|
||||
// BAD!! bad functions
|
||||
|
||||
// TODO: fail if the listview item isn't added
|
||||
return pItem;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
LoadItems -
|
||||
Loads all of the items in a group structure
|
||||
RETURNS -
|
||||
TRUE if successful
|
||||
FALSE otherwise
|
||||
\* * * */
|
||||
BOOL LoadItems(_In_ HWND hWndGroup)
|
||||
{
|
||||
PGROUP pGroup = NULL;
|
||||
PGROUP pNewGroup = NULL;
|
||||
PITEM pItem = NULL;
|
||||
HWND hWndListView = NULL;
|
||||
HIMAGELIST hImageList = NULL;
|
||||
LVITEM lvi = { 0 };
|
||||
UINT cItemIndex = 0;
|
||||
HICON hIcon = NULL;
|
||||
|
||||
// return NULL if we can't get to the group
|
||||
if (hWndGroup == NULL)
|
||||
return FALSE;
|
||||
|
||||
// retrieve the group pointer
|
||||
pGroup = (PGROUP)GetWindowLongPtr(hWndGroup, GWLP_USERDATA);
|
||||
if (pGroup == NULL)
|
||||
return FALSE;
|
||||
|
||||
// get the listview window
|
||||
hWndListView = FindWindowEx(hWndGroup, NULL, WC_LISTVIEW, NULL);
|
||||
if (hWndListView == NULL)
|
||||
return FALSE;
|
||||
|
||||
// make sure we have enough memory for the items
|
||||
pNewGroup = realloc(pGroup, CalculateGroupMemory(pGroup, 0, 1));
|
||||
if (pNewGroup != NULL)
|
||||
{
|
||||
pGroup = pNewGroup;
|
||||
SetWindowLongPtr(hWndGroup, GWLP_USERDATA, (LONG_PTR)pGroup);
|
||||
}
|
||||
|
||||
// then get the pointer to the group's image list
|
||||
hImageList = ListView_GetImageList(hWndListView, LVSIL_NORMAL);
|
||||
|
||||
while (pGroup->cItemArray > cItemIndex)
|
||||
{
|
||||
pItem = pGroup->pItemArray + cItemIndex;
|
||||
|
||||
// extract that icon son!!
|
||||
hIcon = ExtractIcon(g_hAppInstance, (LPWSTR)pItem->szIconPath, pItem->iIconIndex);
|
||||
|
||||
// populate the listview with the relevant information
|
||||
lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
|
||||
lvi.iItem = cItemIndex;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.pszText = pItem->szName;
|
||||
lvi.cchTextMax = ARRAYSIZE(pItem->szName);
|
||||
lvi.iImage = ImageList_AddIcon(hImageList, hIcon);
|
||||
lvi.lParam = (LPARAM)pItem;
|
||||
|
||||
// copy that bad boy into the listview
|
||||
ListView_InsertItem(hWndListView, &lvi);
|
||||
|
||||
cItemIndex++;
|
||||
}
|
||||
|
||||
if (hIcon)
|
||||
// get that hicon outta here
|
||||
DestroyIcon(hIcon);
|
||||
|
||||
// TODO: fail if the listview item isn't added
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
RemoveItem -
|
||||
Removes a program item
|
||||
RETURNS -
|
||||
TRUE if item was successfully removed
|
||||
FALSE otherwise
|
||||
\* * * */
|
||||
BOOL RemoveItem(_In_ PITEM pi)
|
||||
{
|
||||
// TODO: implement this
|
||||
// return NULL if we can't get to the group
|
||||
if (pi == NULL)
|
||||
return FALSE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
ExecuteItem -
|
||||
Runs a program item
|
||||
RETURNS -
|
||||
TRUE if item was successfully ran
|
||||
FALSE otherwise
|
||||
\* * * */
|
||||
BOOL ExecuteItem(_In_ PITEM pi)
|
||||
{
|
||||
// TODO: nCmdShow from program item flags
|
||||
ShellExecute(g_hWndProgMgr, TEXT("open"),
|
||||
pi->szExecPath, NULL,
|
||||
(pi->szWorkPath != TEXT("")) ? pi->szWorkPath : NULL,
|
||||
SW_NORMAL);
|
||||
|
||||
// TODO: if item has run as admin as a flag,
|
||||
// run it as an admin
|
||||
|
||||
// TODO: make sure environment is
|
||||
// refreshed before execution
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
UpdateGroup -
|
||||
Updates group information to prepare
|
||||
it for being saved.
|
||||
ABSTRACT -
|
||||
This function will update all of the
|
||||
relevant structures in a group struct
|
||||
in preparation for saving the group.
|
||||
RETURNS -
|
||||
Nothing.
|
||||
\* * * */
|
||||
VOID UpdateGroup(_In_ PGROUP pg)
|
||||
{
|
||||
DWORD dwFlags = 0;
|
||||
HWND hWndGroup = NULL;
|
||||
|
||||
// Set the important flags
|
||||
pg->dwSignature = GRP_SIGNATURE;
|
||||
pg->wVersion = GRP_VERSION;
|
||||
|
||||
// Set the group checksum
|
||||
pg->wChecksum = 1; // NOTE: implement this for real later lol
|
||||
|
||||
// TODO: set name and group flags
|
||||
// pg->dwFlags = GRP_FLAG_MAXIMIZED;// GetGroupFlags(pgw);
|
||||
|
||||
// Set FILETIME
|
||||
GetSystemTimeAsFileTime(&pg->ftLastWrite);
|
||||
|
||||
if (hWndGroup = GetHwndFromPGroup(pg))
|
||||
{
|
||||
// Get the group window rect and name
|
||||
pg->wp.length = sizeof(WINDOWPLACEMENT);
|
||||
GetWindowPlacement(hWndGroup, &pg->wp);
|
||||
GetWindowText(hWndGroup, pg->szName, ARRAYSIZE(pg->szName));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
GetHwndFromPGroup -
|
||||
In goes a PGROUP out comes a HWND
|
||||
RETURNS -
|
||||
HWND.
|
||||
\* * * */
|
||||
HWND GetHwndFromPGroup(_In_ PGROUP pg)
|
||||
{
|
||||
EnumChildWindows(g_hWndProgMgr, (WNDENUMPROC)GetHwndFromPGroupEnum, (LPARAM)pg);
|
||||
|
||||
return hWndFoundGroup;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
GetHwndFromPGroupEnum -
|
||||
Enum Function
|
||||
RETURNS -
|
||||
HWND.
|
||||
\* * * */
|
||||
BOOL GetHwndFromPGroupEnum(_In_ HWND hwnd, _In_ LPARAM lParam)
|
||||
{
|
||||
if (lParam == GetWindowLongPtr(hwnd, GWLP_USERDATA))
|
||||
{
|
||||
hWndFoundGroup = hwnd;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
hWndFoundGroup = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
VerifyGroup -
|
||||
Verifies that a group contains the
|
||||
correct information about itself.
|
||||
ABSTRACT -
|
||||
This function will check the checksum,
|
||||
verify the number of items, check other
|
||||
parts of the strucutre. If requested,
|
||||
it will repair the group if it is damaged.
|
||||
RETURNS -
|
||||
TRUE if group appears to be fine
|
||||
FALSE if the group is damaged
|
||||
\* * * */
|
||||
BOOL VerifyGroup(_In_ PGROUP pg, _In_ BOOL bRepair)
|
||||
{
|
||||
if (pg->dwSignature != GRP_SIGNATURE)
|
||||
return FALSE;
|
||||
|
||||
// if (pg->wVersion != GRP_VERSION)
|
||||
// some sort of version difference handling
|
||||
|
||||
if (pg->wChecksum == 1234)
|
||||
// TODO: calculate checksum function
|
||||
return FALSE;
|
||||
|
||||
// TODO: use ftlastwrite to throw an error
|
||||
// if system clock is in the future
|
||||
|
||||
// calculate the size of the group based on item of numbers
|
||||
|
||||
// TODO: change to return a dword error value
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
CalculateGroupMemory -
|
||||
Calculates the memory needed by a group.
|
||||
Takes a group structure pointer and the
|
||||
number of desired items as input.
|
||||
RETURNS -
|
||||
Size in bytes that a group should take up.
|
||||
\* * * */
|
||||
UINT CalculateGroupMemory(_In_ PGROUP pGroup, _In_ UINT cItems, _In_ BOOL bLean)
|
||||
{
|
||||
UINT cbGroupSize = 0;
|
||||
UINT cItemBlock = 0;
|
||||
|
||||
// first add the size of a group strucutre
|
||||
cbGroupSize += sizeof(GROUP);
|
||||
|
||||
// calculate the total amount of items wanted
|
||||
cItemBlock = pGroup->cItemArray + cItems;
|
||||
|
||||
if (!bLean)
|
||||
// round the amount of items to the nearest but highest ITEM_BATCH_COUNT
|
||||
cItemBlock = ((cItemBlock + ITEM_BATCH_COUNT) / ITEM_BATCH_COUNT) * ITEM_BATCH_COUNT;
|
||||
|
||||
// finally calculate the total group size
|
||||
cbGroupSize += cItemBlock * sizeof(ITEM);
|
||||
|
||||
return cbGroupSize;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
GroupWndProc -
|
||||
Group window procedure.
|
||||
RETURNS -
|
||||
Zero if nothing, otherwise returns the good stuff.
|
||||
\* * * */
|
||||
LRESULT CALLBACK GroupWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
||||
switch (message)
|
||||
{
|
||||
|
||||
case WM_CREATE:
|
||||
{
|
||||
CREATESTRUCT* pCreateStruct;
|
||||
MDICREATESTRUCT* pMDICreateStruct;
|
||||
|
||||
// code borrowed from winprog
|
||||
pCreateStruct = (CREATESTRUCT*)lParam;
|
||||
pMDICreateStruct = (MDICREATESTRUCT*)pCreateStruct->lpCreateParams;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_CONTEXTMENU:
|
||||
{
|
||||
POINT pt = { 0 };
|
||||
HMENU hMenu = NULL;
|
||||
BOOL bPopup = FALSE;
|
||||
|
||||
// LVHT_ONITEM
|
||||
// LVHT_NOWHERE
|
||||
|
||||
pt.x = GET_X_LPARAM(lParam);
|
||||
pt.y = GET_Y_LPARAM(lParam);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_CLOSE:
|
||||
return ShowWindow(hWnd, SW_MINIMIZE);
|
||||
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
LPNMHDR lpnmhdr = (LPNMHDR)lParam;
|
||||
HWND hWndListView = NULL;
|
||||
|
||||
// find the listview control
|
||||
hWndListView = FindWindowEx(hWnd, NULL, WC_LISTVIEW, NULL);
|
||||
if (hWndListView == NULL)
|
||||
break;
|
||||
|
||||
switch (lpnmhdr->code)
|
||||
{
|
||||
|
||||
case NM_DBLCLK:
|
||||
{
|
||||
LVITEM lvi = { 0 };
|
||||
PITEM pItem = NULL;
|
||||
|
||||
// what info do we want?
|
||||
lvi.mask = LVIF_PARAM;
|
||||
lvi.iItem = ((LPNMITEMACTIVATE)lParam)->iItem;
|
||||
|
||||
// get the listview item
|
||||
ListView_GetItem(hWndListView, &lvi);
|
||||
|
||||
// get the item pointer
|
||||
pItem = (PITEM)lvi.lParam;
|
||||
|
||||
// verify...
|
||||
if (pItem)
|
||||
{
|
||||
// and execute!
|
||||
ExecuteItem(pItem);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_SIZE:
|
||||
{
|
||||
HWND hWndListView = NULL;
|
||||
RECT rcGroupWindow = { 0 };
|
||||
|
||||
// get the group window rect
|
||||
GetClientRect(hWnd, &rcGroupWindow);
|
||||
|
||||
// find the listview control
|
||||
hWndListView = FindWindowEx(hWnd, NULL, WC_LISTVIEW, NULL);
|
||||
if (hWndListView == NULL)
|
||||
break;
|
||||
|
||||
// resize it to fit the window
|
||||
SetWindowPos(hWndListView, NULL,
|
||||
rcGroupWindow.left, rcGroupWindow.top,
|
||||
rcGroupWindow.right - rcGroupWindow.left,
|
||||
rcGroupWindow.bottom - rcGroupWindow.top, SWP_NOZORDER);
|
||||
|
||||
return DefMDIChildProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
default:
|
||||
return DefMDIChildProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
Reference in New Issue
Block a user