dipslib.c

来自「一本已经绝版的好书」· C语言 代码 · 共 292 行

C
292
字号
/************************************************************
Module name: DIPSLib.c
Notices: Copyright (c) 1996 Jeffrey Richter
************************************************************/


#include "..\CmnHdr.H"                  /* See Appendix C. */
#include <Windows.H>
#include <WindowsX.H>
#include <CommCtrl.H>

#define DIPSLIBAPI __declspec(dllexport)
#include "DIPSLib.H"
#include "Resource.H"


/////////////////////////////////////////////////////////////


#ifdef _DEBUG
// This function forces the debugger to be invoked
void ForceDebugBreak() {
   __try { DebugBreak(); }
   __except(UnhandledExceptionFilter(
      GetExceptionInformation())) {
   }
}
#else
#define ForceDebugBreak()
#endif


/////////////////////////////////////////////////////////////


// Forward references
LRESULT WINAPI GetMsgProc (int nCode, WPARAM wParam, LPARAM lParam);
BOOL WINAPI DIPS_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);


/////////////////////////////////////////////////////////////


// Instruct the compiler to put the g_hhook data variable in 
// its own data section called Shared. We then instruct the 
// linker that we want to share the data in this section 
// with all instances of this application.
#pragma data_seg("Shared")
HHOOK g_hhook = NULL;
DWORD g_dwThreadIdDIPS = 0;
#pragma data_seg()

// Instruct the linker to make the Shared section 
// readable, writable, and shared.
#pragma comment(linker, "/section:Shared,rws")


/////////////////////////////////////////////////////////////


// Nonshared variables
HINSTANCE g_hinstDll = NULL;


/////////////////////////////////////////////////////////////


BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID fImpLoad) {

   switch (fdwReason) {

      case DLL_PROCESS_ATTACH:
         // DLL is attaching to the address space
         // of the current process.
         g_hinstDll = hinstDll;
         break;

      case DLL_THREAD_ATTACH:
         // A new thread is being created
         // in the current process.
         break;

      case DLL_THREAD_DETACH:
         // A thread is exiting cleanly.
         break;

      case DLL_PROCESS_DETACH:
         // The calling process is detaching the
         // DLL from its address space.
         break;
   }
   return(TRUE);
}


/////////////////////////////////////////////////////////////


BOOL WINAPI SetDIPSHook(DWORD dwThreadId) {
   BOOL fOk = FALSE;
   
   if (dwThreadId != 0) {
      // Make sure that the hook is not already installed.
      chASSERT(g_hhook == NULL);

      // Save our thread ID in a shared variable so that
      // our GetMsgProc function can post a message back to
      // to thread when the server window has been created.
      g_dwThreadIdDIPS = GetCurrentThreadId();

      // Install the hook on the specified thread
      g_hhook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, 
         g_hinstDll, dwThreadId);

      fOk = (g_hhook != NULL);
      if (fOk) {
         // The hook was installed successfully; force a
         // benign message to the thread's queue so that 
         // the hook function gets called.
         fOk = PostThreadMessage(dwThreadId, WM_NULL, 0, 0);
      }
   } else {

      // Make sure that a hook has been installed.
      chASSERT(g_hhook != NULL);
      fOk = UnhookWindowsHookEx(g_hhook);
      g_hhook = NULL;
   }

   return(fOk);
}


/////////////////////////////////////////////////////////////


LRESULT WINAPI GetMsgProc (int nCode, 
   WPARAM wParam, LPARAM lParam) {

   static BOOL fFirstTime = TRUE;

   if (fFirstTime) {
      // The DLL just got injected.
      fFirstTime = FALSE;

      // Uncomment the line below to invoke the debugger
      // on the process that just got the injected DLL.
      // ForceDebugBreak();

      // Create the DTIS Server window to 
      // handle the client request.
      CreateDialog(g_hinstDll, MAKEINTRESOURCE(IDD_DIPS), 
         NULL, DIPS_DlgProc);

      // Tell the DIPS application that the server is
      // up and ready to handle requests.
      PostThreadMessage(g_dwThreadIdDIPS, WM_NULL, 0, 0);
   }

   return(CallNextHookEx(g_hhook, nCode, wParam, lParam));
}


/////////////////////////////////////////////////////////////


void DIPS_OnClose(HWND hwnd) {
   DestroyWindow(hwnd);
}


/////////////////////////////////////////////////////////////


static const TCHAR g_szRegSubKey[] = 
   __TEXT("Software\\Richter\\Desktop Item Position Saver");


/////////////////////////////////////////////////////////////


void SaveListViewItemPositions(HWND hwndLV) {
   int nItem, nMaxItems = ListView_GetItemCount(hwndLV);
   HKEY hkey;
   DWORD dwDisposition;

   // When saving new positions, delete the old position 
   // information that is currently in the registry.
   LONG l = RegDeleteKey(HKEY_CURRENT_USER, g_szRegSubKey);

   // Create the registry key to hold the info
   l = RegCreateKeyEx(HKEY_CURRENT_USER, g_szRegSubKey,
      0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, 
      NULL, &hkey, &dwDisposition);
   chASSERT(l == ERROR_SUCCESS);

   for (nItem = 0; nItem < nMaxItems; nItem++) {
      TCHAR szName[_MAX_PATH];
      POINT pt;

      // Get the name and position of a listview item.
      ListView_GetItemText(hwndLV, nItem, 0, szName, chDIMOF(szName));
      ListView_GetItemPosition(hwndLV, nItem, &pt);

      // Save the name and position in the registry.
      l = RegSetValueEx(hkey,	szName, 0, 
         REG_BINARY, (PBYTE) &pt, sizeof(pt));
      chASSERT(l == ERROR_SUCCESS);
   }
   RegCloseKey(hkey);
}


/////////////////////////////////////////////////////////////


void RestoreListViewItemPositions(HWND hwndLV) {
   HKEY hkey;
   LONG l = RegOpenKeyEx(HKEY_CURRENT_USER, g_szRegSubKey,
      0, KEY_QUERY_VALUE, &hkey);
   if (l == ERROR_SUCCESS) {
      int nIndex;

      // If the listview has AutoArrange on, 
      // temporarily turn it off.
      DWORD dwStyle = GetWindowStyle(hwndLV);
      if (dwStyle & LVS_AUTOARRANGE) 
         SetWindowLong(hwndLV, GWL_STYLE, 
            dwStyle & ~LVS_AUTOARRANGE);

      l = NO_ERROR;
      for (nIndex = 0; l != ERROR_NO_MORE_ITEMS; nIndex++) {
         TCHAR szName[_MAX_PATH];
         POINT pt;
         LV_FINDINFO lvfi;
         int cbValueName = chDIMOF(szName);
         int cbData = sizeof(pt), nItem;
         DWORD dwType;

         // Read a value name and position from the registry.
         l = RegEnumValue(hkey, nIndex, szName, &cbValueName, 
            NULL, &dwType, (PBYTE) &pt, &cbData);

         if (l == ERROR_NO_MORE_ITEMS) 
            continue;

         if ((dwType == REG_BINARY) && (cbData == sizeof(pt))) {
            // The value is something that we recognize; try to find
            // an item in the listview control that matches the name.
            lvfi.flags = LVFI_STRING; 
            lvfi.psz = szName; 
            nItem = ListView_FindItem(hwndLV, -1, &lvfi);
            if (nItem != -1) {
               // We found a match; change the item's position.
               ListView_SetItemPosition(hwndLV, nItem, pt.x, pt.y);	
            }
         }
      }
      // Turn AutoArrange back on if it was originally on.
      SetWindowLong(hwndLV, GWL_STYLE, dwStyle);
      RegCloseKey(hkey);
   }
}


/////////////////////////////////////////////////////////////


BOOL WINAPI DIPS_DlgProc(HWND hwnd, UINT uMsg, 
   WPARAM wParam, LPARAM lParam) {

   switch (uMsg) {
      chHANDLE_DLGMSG(hwnd, WM_CLOSE, DIPS_OnClose);

      case WM_APP:
         // Uncomment the line below to invoke the debugger
         // on the process that just got the injected DLL.
         // ForceDebugBreak();

         if (lParam) 
            SaveListViewItemPositions((HWND) wParam);
         else 
            RestoreListViewItemPositions((HWND) wParam);
         break;
   }
   return(FALSE);
}



//////////////////////// End of File ////////////////////////

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?