📄 gwcommand.cpp
字号:
MENUITEMINFO miiInfo={sizeof(MENUITEMINFO), 0};
miiInfo.fMask=MIIM_TYPE|MIIM_DATA;
char *pszMenuString=NULL;
char *pszMainMenuString=NULL;
DWORD dwMenuStringLen=0;
int iMenuIndex=0;
HWND hWndReBar=NULL, hWndTBar=NULL;
LPSUBCLASSINFO lpSubClassInfo=NULL;
//get our menu string
pgpAssert(NULL == pszMainMenuString);
bRet=SafeLoadString(IDS_GWPLUGIN_MAIN_MENU_NAME, &pszMainMenuString);
if((FALSE == bRet) || (NULL == pszMainMenuString))
{
bRet=FALSE;
goto cleanup;
}
//for all the top level menu items in the menu bar
for(iMenuIndex=0; TRUE == bMoreItemsExist; iMenuIndex++)
{
//get the length of string for the menu involved
miiInfo.cch=0;
miiInfo.dwTypeData=NULL;
bMoreItemsExist=GetMenuItemInfo(hMenuBar, iMenuIndex, TRUE, &miiInfo);
if(FALSE == bMoreItemsExist)//we assume all failures are because of the item being not there
break;//we are done with all menu items
//if the length required is less than is allocated
pgpAssert(TRUE == bMoreItemsExist);
if(dwMenuStringLen < (miiInfo.cch+1))
{
//allocate the required amount of buffer
char *pszTempPtr=(char *)realloc(pszMenuString, miiInfo.cch+1);
if(NULL == pszTempPtr)
{
pgpAssert(FALSE);
bRet=FALSE;
goto cleanup;
}
//switch to the new buffer and reset contents
pszMenuString=pszTempPtr;
dwMenuStringLen=miiInfo.cch+1;
ZeroMemory(pszMenuString, dwMenuStringLen);
}
//get the menu item text
pgpAssert(NULL != pszMenuString);
pgpAssert(!IsBadWritePtr(pszMenuString, dwMenuStringLen));
miiInfo.dwTypeData=pszMenuString;
miiInfo.cch=dwMenuStringLen;
bRet=GetMenuItemInfo(hMenuBar, iMenuIndex, TRUE, &miiInfo);
pgpAssert(TRUE == bRet);
if(FALSE == bRet)
goto cleanup;//certainly some error condition
//if it is not our menu item
pgpAssert(NULL != pszMainMenuString);
if(0 != strcmpi(pszMenuString, pszMainMenuString))
{
bRet=EnableMenuItem(hMenuBar, iMenuIndex,
MF_BYPOSITION|(bEnable?MF_ENABLED:MF_GRAYED));
pgpAssert(-1 != bRet);//if this fails it is difficult to handle error condition
//because we need to undo some of the things we have done already !!
//the previous menu state should be the opposite of what we just did
pgpAssert(bEnable?(MF_GRAYED == (MF_GRAYED&bRet)):(MF_ENABLED == (MF_ENABLED&bRet)));
}
//get rid of the string (lets stay clean)
ZeroMemory(pszMenuString, dwMenuStringLen);
}
//control comes here only if we have succeeded in all changes till now
bRet=DrawMenuBar(m_hCtxtWindow);//redraw menubar
pgpAssert(TRUE == bRet);
//get the rebar window
hWndReBar=GetWindow(GWO_CURRENTREBAR_WINDOW);
pgpAssert(NULL != hWndReBar);
if(NULL == hWndReBar)
{
bRet=FALSE;
goto cleanup;
}
//for all the toolbars under the rebar
while(NULL != (hWndTBar=FindWindowEx(hWndReBar, hWndTBar, TOOLBARCLASSNAME, NULL)))
{
//if the toolbar is not visible go over to the next toolbar
if(!IsWindowVisible(hWndTBar))
{
PgpGwTrace("toolbar (%#x) is invisible. skipping...\n", hWndTBar);
continue;
}
//subclass the toolbar so that we can do all our stuff of disabling/enabling
//and other odd and sundry things that GroupFool forces us to
//first check if we have already got our property stored with it
lpSubClassInfo=(LPSUBCLASSINFO)GetProp(hWndTBar, MODULENAME);
if(NULL == lpSubClassInfo)//if it has not been subclassed
{
pgpAssert(NULL == lpSubClassInfo);
lpSubClassInfo=(LPSUBCLASSINFO)calloc(sizeof(SUBCLASSINFO), 1);
if(NULL != lpSubClassInfo)
{
//fill up the struct with the original window proc of the toolbar control
lpSubClassInfo->wpOrigProc=(WNDPROC)GetWindowLong(hWndTBar, GWL_WNDPROC);
pgpAssert(NULL != lpSubClassInfo->wpOrigProc);
//store the info in our property for the toolbar.
_VERIFY(0 != SetProp(hWndTBar, MODULENAME, (HANDLE)lpSubClassInfo));
lpSubClassInfo=NULL;
//subclass now - since the subclass proc can get the details from subclassinfo
SetWindowLong(hWndTBar, GWL_WNDPROC, (LONG)SubClassedToolBarWndProc);
}
}
SendMessage(hWndTBar, WM_ENABLECOMMANDS, bEnable, 0L);
}
cleanup:
if(NULL != pszMenuString)
{
free(pszMenuString);
pszMenuString=NULL;
dwMenuStringLen=0;
}
if(NULL != pszMainMenuString)
{
free(pszMainMenuString);
pszMainMenuString=NULL;
}
return bRet;
}
VOID WINAPI GWEventNotify (DWORD dwID, DWORD dwEvent)
{
switch (dwEvent)
{
case EVT_GROUPWISE_CANCEL_ITEM:
case EVT_GROUPWISE_CLOSE_ITEM:
case EVT_GROUPWISE_SEND_ITEM_COMPLETED:
//return ODMA document to the DMS
//ODMCloseDoc(g_hODMA, (LPSTR)dwID, 0, 0, NULL, 0);
//delete memory used to store the DocId
//delete (LPSTR) dwID;
break;
}
}
LRESULT CALLBACK DecryptVerifyWndProc(HWND hWnd, UINT uiMessageId, WPARAM wParam, LPARAM lParam)
{
static HWND hCurWnd=NULL;
static LPSUBCLASSINFO lscInfo=NULL;
static HACCEL hAccTable=NULL;
LONG lRet=0;
if(hWnd != hCurWnd)
{
hCurWnd=hWnd;
pgpAssert(NULL != hCurWnd);
lscInfo=(LPSUBCLASSINFO)GetProp(hWnd, MODULENAME);
pgpAssert(NULL != lscInfo);
pgpAssert(!IsBadWritePtr(lscInfo, sizeof(SUBCLASSINFO)));
}
pgpAssert((NULL != lscInfo) && (NULL != lscInfo->wpOrigProc));
if(!((NULL != lscInfo) && (NULL != lscInfo->wpOrigProc)))
{
PgpGwTrace("Warning: window message(%#x) not processed by decrypt/verify window !!\n", uiMessageId);
return 0L;
}
switch(uiMessageId)
{
case WM_CONTEXTMENU:
{
pgpAssert(hWnd == (HWND)wParam);
POINT posClient={0};
POINT pos={GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
LONG lRet=0;
BOOL bRet=TRUE;
HMENU hCtxtMenu=NULL;
char szTmpBuffer[255]={0};
//check if there is any selected text in the window
lRet=SendMessage(hWnd, EM_SELECTIONTYPE, 0, 0);
if(SEL_EMPTY == lRet)//no selection so no context menu
goto contextmenu_cleanup;
//if the context menu is generated from SHIFT+F10 or VK_APPS then get
//the position of cursor in the area and show there
if((-1 == pos.x) && (-1 == pos.y))
GetCursorPos(&pos);
//convert the screen coords to client coordinate system
posClient=pos;
ScreenToClient(hWnd, &posClient);
//now positions should be something positive
pgpAssert(pos.x >= 0 && pos.y >= 0);
pgpAssert(posClient.x >= 0 && posClient.y >= 0);
hCtxtMenu=CreatePopupMenu();
pgpAssert(NULL != hCtxtMenu);
if(NULL == hCtxtMenu)
goto contextmenu_cleanup;
//get the command string from resource
lRet=LoadString(g_hInstance, IDS_COMMAND_COPY, szTmpBuffer, sizeof(szTmpBuffer));
pgpAssert(lRet > 0);//string is not found or some error condition
pgpAssert(lRet != sizeof(szTmpBuffer)-sizeof(char));//potential truncation otherwise
//insert a copy command into the context menu
bRet=AppendMenu(hCtxtMenu, MF_ENABLED|MF_STRING, IDM_COPY, szTmpBuffer);
pgpAssert(TRUE == bRet);
if(FALSE == bRet)
goto contextmenu_cleanup;
//show the context menu
bRet=TrackPopupMenu(hCtxtMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD,
pos.x, pos.y, 0, hWnd, NULL);
if(0 == bRet)//some error or user cancelled
goto contextmenu_cleanup;
//if copy command was given to us
if(IDM_COPY == bRet)
SendMessage(hWnd, WM_COPY, 0, 0);//copy selection to clipboard
contextmenu_cleanup:
if(NULL != hCtxtMenu)
{
DestroyMenu(hCtxtMenu);
hCtxtMenu=NULL;
}
}
break;
case WM_KEYDOWN:
{
pgpAssert(2 == sizeof(SHORT));
PgpGwTrace("wparam=%#x lparam=%#x\n", wParam, lParam);
//if it is the character c/C
if((wParam == 'c') || (wParam == 'C'))
{
SHORT shState=GetKeyState(VK_CONTROL);
PgpGwTrace("state=%#x\n", shState);
if(shState&0x8000)//while control key is down
PostMessage(hWnd, WM_COPY, 0, 0);
}
goto call_default;
}
break;
case WM_COMMAND:
{
goto call_default;
}
break;
case WM_DESTROY:
{
//let it be processed by the orig wnd proc
lRet=CallWindowProc(lscInfo->wpOrigProc, hWnd,
uiMessageId, wParam, lParam);//let the orig wndproc handle it
//we want this to be the last message processed by us.
//so we subclass again and bail out
pgpAssert(NULL != lscInfo->wpOrigProc);
_VERIFY((LONG)DecryptVerifyWndProc ==
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)lscInfo->wpOrigProc));
_VERIFY(lscInfo == RemoveProp(hWnd, MODULENAME));
//free the subclass info we had put in our property for the window
free(lscInfo);
lscInfo=NULL;
//destroy the accelerator table
DestroyAcceleratorTable(hAccTable);
}
break;
default:
call_default:
return CallWindowProc(lscInfo->wpOrigProc, hWnd,
uiMessageId, wParam, lParam);//let the orig wndproc handle it
break;
}
return lRet;
}
LRESULT CALLBACK SubClassedMsgBodyWndProc(HWND hWnd, UINT uiMessageId, WPARAM wParam, LPARAM lParam)
{
static HWND hCurWnd=NULL;
static LPSUBCLASSINFO lscInfo=NULL;
LONG lRet=0;
if(hWnd != hCurWnd)
{
hCurWnd=hWnd;
pgpAssert(NULL != hCurWnd);
lscInfo=(LPSUBCLASSINFO)GetProp(hWnd, MODULENAME);
pgpAssert(NULL != lscInfo);
pgpAssert(!IsBadWritePtr(lscInfo, sizeof(SUBCLASSINFO)));
}
pgpAssert((NULL != lscInfo) && (NULL != lscInfo->wpOrigProc));
if(!((NULL != lscInfo) && (NULL != lscInfo->wpOrigProc)))
{
PgpGwTrace("Warning: window message(%#x) not processed by message text window !!\n", uiMessageId);
return 0L;
}
switch(uiMessageId)
{
case WM_SIZE://size of this control has changed
{
//get the screen coordinates of the control
RECT rcCtrlRect={0};
POINT ptTmpPoint={0};
_VERIFY(GetWindowRect(hWnd, &rcCtrlRect));
//convert the top left corner to client coords
ptTmpPoint.x=rcCtrlRect.left;
ptTmpPoint.y=rcCtrlRect.top;
_VERIFY(ScreenToClient(GetParent(hWnd), &ptTmpPoint));
//move the other control to the same position as this
pgpAssert(NULL != lscInfo->hWndOther);
_VERIFY(MoveWindow(lscInfo->hWndOther, ptTmpPoint.x, ptTmpPoint.y,
abs(rcCtrlRect.right-rcCtrlRect.left),
abs(rcCtrlRect.bottom-rcCtrlRect.top), TRUE));
pgpAssert(NULL != lscInfo->wpOrigProc);
return CallWindowProc(lscInfo->wpOrigProc, hWnd,
uiMessageId, wParam, lParam);//let the orig wndproc handle it
}
break;
case WM_DESTROY:
{
//let it be processed by the orig wnd proc
lRet=CallWindowProc(lscInfo->wpOrigProc, hWnd,
uiMessageId, wParam, lParam);//let the orig wndproc handle it
//we want this to be the last message processed by us.
//so we subclass again and bail out
pgpAssert(NULL != lscInfo->wpOrigProc);
_VERIFY((LONG)SubClassedMsgBodyWndProc ==
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)lscInfo->wpOrigProc));
_VERIFY(lscInfo == RemoveProp(hWnd, MODULENAME));
//free the subclass info we had put in our property for the window
free(lscInfo);
lscInfo=NULL;
}
break;
default:
return CallWindowProc(lscInfo->wpOrigProc, hWnd,
uiMessageId, wParam, lParam);//let the orig wndproc handle it
break;
}
return lRet;
}
LRESULT CALLBACK SubClassedToolBarWndProc(HWND hTBarWnd, UINT uiMessageId, WPARAM wParam, LPARAM lParam)
{
static HWND hCurWnd=NULL;//cached window handle for context change
static LPSUBCLASSINFO lscInfo=NULL;//cached subclassinfo
LONG lRet=0;
//if this is the very first time we are called or we have just been
//called for a different window handle than before
if((NULL == hCurWnd) || (hCurWnd != hTBarWnd))
{
hCurWnd=hTBarWnd;//update the cur window handle cache
//we need to update the subclass info
lscInfo=(LPSUBCLASSINFO)GetProp(hCurWnd, MODULENAME);
pgpAssert(NULL != lscInfo);
pgpAssert(!IsBadWritePtr(lscInfo, sizeof(SUBCLASSINFO)));
}
pgpAssert((NULL != lscInfo) && (NULL != lscInfo->wpOrigProc));
if(!((NULL != lscInfo) && (NULL != lscInfo->wpOrigProc)))
{
PgpGwTrace("Warning: window message(%#x) not processed by message text window !!\n", uiMessageId);
return 0L;
}
switch(uiMessageId)
{
case WM_DESTROY:
{
//let it be processed by the orig wnd proc
lRet=CallWindowProc(lscInfo->wpOrigProc, hTBarWnd,
uiMessageId, wParam, lParam);//let the orig wndproc handle it
//we want this to be the last mes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -