j'ai un code source intiulé pour caché les icones de taskbar , je veut le modifié : d'ajouté un bouton scrol comme en windows xp a la barre des étaches donc il faut modifié le code en plaçant la deplacement de souris pour caché les icones en un seul click sur un bouton comme winXP et voila le code source :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
/*
 Tray Magician v1.1
 
 Copyright © 1999 Ziff-Davis, Inc.
    All rights reserved.
 
 First published in PC Magazine, US Edition,
    December 14, 1999.
 
 Written by Ignacio Alvarez
 
 
    This file implements traymagc.dll, which contains the hooks -
    and most of the program functionality.
 
 
*/
 
 
#include "stdafx.h"
#include <shellapi.h>
 
 
// The following data section is shared by all instances of the DLL
#pragma comment(linker, "/SECTION:.shared,RWS")
#pragma data_seg(".shared")
//static HWND hDebug  = 0;
static HWND hTrayMagic  = 0;
static  HHOOK hMouseHook  = 0;
static  HHOOK hGetHook  = 0;
static BOOL LDown   = FALSE;
static HWND hWindow   = 0;
static HWND hTaskbar  = 0;
static HWND hTray   = 0;
static HWND hTaskSw   = 0;
static HWND hReBar   = 0;
static HWND hClock   = 0;
static WNDPROC OldProc   = NULL;
static BOOL Restoring  = FALSE;
static BOOL ShowClock  = FALSE;
static BOOL WinNT   = FALSE;
static UINT RestoreMsg  = 0;
static UINT BeginSubclassing= 0;
static UINT EndSubclassing = 0;
#pragma data_seg()
 
 
// This structure is used when intercepting the WM_COPYDATA messages -
// that carry the NOTIFYICONDATA information.
typedef struct
{
 long   Filler;
 long   Operation;
 NOTIFYICONDATA Data;
} CINFO;
 
// Same structure as above but uses the wide version of NOTIFYICONDATA -
// for compatibility with NT
typedef struct
{
 long   Filler;
 long   Operation;
 NOTIFYICONDATAW Data;
} CINFOW;
 
// This structure is used to cache modifications to the Tray icons -
// in order to prevent Windows from excessively rebuilding the Tray.
typedef struct
{
 HWND hwnd;
 WPARAM wParam;
 CINFO Info;
 CINFOW InfoW;
 DWORD dwData;
 BOOL Empty;
} CACHE;
 
static CACHE  cache[64];
static int   ccount  = 0;
static HINSTANCE hInstance = 0;
static  POINT  PrevPos;
static  RECT  WindowRect;
 
 
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
      )
{
    hInstance = (HINSTANCE)hModule;
 switch (ul_reason_for_call)
 {
  case DLL_PROCESS_ATTACH:
  case DLL_THREAD_ATTACH:
  case DLL_THREAD_DETACH:
  case DLL_PROCESS_DETACH:
   break;
    }
    return TRUE;
}
 
 
// This function was borrowed from Steven E. Sipe's excellent Tray Manager.
HICON MyCopyIcon(HICON hIcon)
{
 ICONINFO info;
 HICON hIconNew;
 
 // Get information about the specified icon
 GetIconInfo(hIcon,&info);
 
 // Create a clone of the icon
 hIconNew = CreateIconIndirect(&info);
 
 // Delete the info item's bitmaps -- otherwise we get a very
 // ugly memory leak
 DeleteObject(info.hbmMask);
 DeleteObject(info.hbmColor);
 
 return(hIconNew);
}
 
 
 
// This function returns TRUE if running in NT
BOOL IsWinNT(void)
{
 OSVERSIONINFO os;
 os.dwOSVersionInfoSize = sizeof(os);
 GetVersionEx(&os);
 return (os.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
 
 
 
// Tray Magician intercepts and stores modifications to the Tray in a cache,
// this function reads the cache and passes the intercepted modifications -
// back to the Tray.
void FlushCache(void)
{
 COPYDATASTRUCT Data;
 Data.cbData = sizeof(Data);
 // It steps through each of the items in the cache array
 for(int i = 0; i < ccount; i++)
  // The cache array has an empty flag to indicate wether each -
  // element is being used.
  if(!cache[i].Empty)
  {
   UINT uFlags;
   Data.dwData = cache[i].dwData;
   // If running in NT the wide element of the array is used
   if(WinNT)
   {
    Data.cbData = sizeof(CINFOW);
    Data.lpData = &(cache[i].InfoW);
    uFlags = cache[i].InfoW.Data.uFlags;
   }
   else
   {
    Data.cbData = sizeof(CINFO);
    Data.lpData = &(cache[i].Info);
    uFlags = cache[i].Info.Data.uFlags;
   }
   // It calls the original Taskbar WindowProc passing it the -
   // modification stored in each cache item.
   if(OldProc)
    CallWindowProc(OldProc, cache[i].hwnd, WM_COPYDATA, cache[i].wParam, (DWORD)&Data);
   cache[i].Empty = TRUE;
   if(WinNT)
   {
    if(cache[i].InfoW.Data.uFlags & NIF_ICON)
     DestroyIcon(cache[i].InfoW.Data.hIcon);
   }
   else
   {
    if(cache[i].Info.Data.uFlags & NIF_ICON)
     DestroyIcon(cache[i].Info.Data.hIcon);
   }
  }
 ccount = 0;
}
 
 
 
// This function returns TRUE if the Tray is currently hidden by Tray Magician
BOOL IsTrayMinimized(void)
{
 RECT Taskbar, Tray;
 GetWindowRect(hTaskbar, &Taskbar);
 GetWindowRect(hTray, &Tray);
 if(Taskbar.right - Taskbar.left > Taskbar.bottom - Taskbar.top)
  return (Tray.right > Taskbar.right);
 else
  return (Tray.bottom > Taskbar.bottom);
}
 
 
 
// This function posts a user-defined message to the TrayMagician.exe window -
// indicating that the Tray should be unhidden.
void CALLBACK RestoreTray(void)
{
 // The Restoring flag is used to prevent another message from being posted,
 // while there's a previous one pending. It is done to prevent an -
 // excessive flicker of the Tray.
 if(!Restoring)
 {
  Restoring = TRUE;
  PostMessage(hTrayMagic, RestoreMsg, 0, 0);
 }
}
 
 
 
// This function takes care of hiding/restoring the system tray
void HideRestoreTray(void)
{
 RECT Taskbar, Tray, ReBar, TaskSw, Clock;
 POINT Pos;
 GetWindowRect(hTaskbar, &Taskbar);
 GetWindowRect(hReBar, &ReBar);
 GetWindowRect(hTaskSw, &TaskSw);
 GetWindowRect(hTray, &Tray);
 GetWindowRect(hClock, &Clock);
 GetCursorPos(&Pos);
 // If the mouse is moving inside any part of the Tray, it restores it if hidden
 if(IsTrayMinimized())
 {
  if(PtInRect(&Tray, Pos))
  {
   FlushCache();
   RestoreTray();
  }
 }
 // Else it hides it
 else if(!PtInRect(&Tray, Pos))
 {
  int Delta;
  POINT ChildPos = Pos;
  ScreenToClient(hTaskbar, &ChildPos);
  HWND Under = WindowFromPoint(Pos);
  HWND ChildUnder = ChildWindowFromPoint(hTaskbar, ChildPos);
  if(!(Under == hTaskbar && !ChildUnder))
  {
   // If the Taskbar is horizontal
   if(Taskbar.bottom - Taskbar.top < Taskbar.right - Taskbar.left)
   {
    Pos.x = Tray.right - 2;
    if(ShowClock)
     if(Clock.left != Clock.right)
      Pos.x = Clock.left - 1;
    if(Pos.x != Tray.left)
    {
     Delta = Pos.x - Tray.left;   
     ScreenToClient(hTaskbar, &Pos);
     Pos.y = 0;
     // The Tray, and several of the Taskbar child windows need to be moved and/or
     // resized in order to minimize the Tray.
     if(ShowClock)
      SetWindowPos(hClock, 0, 0, 1, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
     SetWindowPos(hTray, 0, Pos.x, Pos.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
     SetWindowPos(hReBar, 0, 0, 0, ReBar.right - ReBar.left + Delta , ReBar.bottom - ReBar.top, SWP_NOMOVE | SWP_NOZORDER);
     SetWindowPos(hTaskSw, 0, 0, 0, TaskSw.right - TaskSw.left + Delta, TaskSw.bottom - TaskSw.top, SWP_NOMOVE | SWP_NOZORDER);
     // RedrawWindow() is called to insure that the Taskbar is repainted
     RedrawWindow(hTaskbar, NULL, NULL, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE);
     RedrawWindow(hTray, NULL, NULL, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE);
     SetWindowPos(hReBar, 0, 0, 0, ReBar.right - ReBar.left + Delta , ReBar.bottom - ReBar.top, SWP_NOMOVE | SWP_NOZORDER);
     SetWindowPos(hTaskSw, 0, 0, 0, TaskSw.right - TaskSw.left + Delta, TaskSw.bottom - TaskSw.top, SWP_NOMOVE | SWP_NOZORDER);
     if(ShowClock)
      SetWindowPos(hClock, 0, 0, 1, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
    }
   }
   // Else If the Taskbar is vertical
   else
   {
    Tray.bottom += 10;
    if(Tray.top > 10 && !PtInRect(&Tray, Pos))
    {
     Pos.y = Tray.bottom - 12;
     if(ShowClock)
      if(Clock.left != Clock.right)
       Pos.y -= Clock.bottom - Clock.top - 2;
     if(Pos.y != Tray.top)
     {
      Delta = Pos.y - Tray.top;
      ScreenToClient(hTaskbar, &Pos);
      Pos.x = ((Taskbar.right - Taskbar.left) - (Tray.right - Tray.left)) / 2 - 4;
      // The Tray, and several of the Taskbar child windows need to be moved and/or
      // resized in order to minimize the Tray.
      SetWindowPos(hTray, 0, Pos.x, Pos.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
      SetWindowPos(hReBar, 0, 0, 0, ReBar.right - ReBar.left, ReBar.bottom - ReBar.top + Delta, SWP_NOMOVE | SWP_NOZORDER);
      SetWindowPos(hTaskSw, 0, 0, 0, TaskSw.right - TaskSw.left, TaskSw.bottom - TaskSw.top + Delta, SWP_NOMOVE | SWP_NOZORDER);
      // RedrawWindow() is called to insure that the Taskbar is repainted
      RedrawWindow(hTaskbar, NULL, NULL, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE);
      RedrawWindow(hTray, NULL, NULL, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE);
      SetWindowPos(hReBar, 0, 0, 0, ReBar.right - ReBar.left, ReBar.bottom - ReBar.top + Delta, SWP_NOMOVE | SWP_NOZORDER);
      SetWindowPos(hTaskSw, 0, 0, 0, TaskSw.right - TaskSw.left, TaskSw.bottom - TaskSw.top + Delta, SWP_NOMOVE | SWP_NOZORDER);
     }
    }
   }
  }
 }
}
 
 
 
// The Taskbar is subclassed by replacing its WindowProc with TaskbarProc
LRESULT CALLBACK TaskbarProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
 __try
 {
  BOOL ClearRestoring = FALSE;
  // If the Show Clock option is used, sometimes Windows fails to correctly -
  // restore the clock position when it repaints the Taskbar,
  // so SetWindowPos() is explicitly called to fix this problem.
  if(!IsTrayMinimized())
  {
   RECT Tray, Clock;
   GetWindowRect(hTray, &Tray);
   GetWindowRect(hClock, &Clock);
   if(Tray.right - Clock.right > 2)
    SetWindowPos(hClock, 0, (Tray.right - Tray.left) - (Clock.right - Clock.left) - 1, 1, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
  }
 
  // The WM_COPYDATA message is processed to intercept modifications to -
  // the Tray while it's minimized.
  if(Message == WM_COPYDATA)
  {
   PCOPYDATASTRUCT pData = (PCOPYDATASTRUCT) lParam;
   if(pData)
    if(pData->dwData == 1)
     if(pData->lpData)
     {
      CINFOW *pInfoW;
      CINFO *pInfo;
      long Operation;
 
      // If running in NT, the wide version of CINFO is used
      if(WinNT)
      {
       pInfoW = (CINFOW *)pData->lpData;
       Operation = pInfoW->Operation;
      }
      else
      {
       pInfo = (CINFO *)pData->lpData;
       Operation = pInfo->Operation;
      }
      // The modifications are only intercepted if the Tray is hidden,
      // to prevent unwanted flashing of the Tray, this is because Windows -
      // attempts to rebuild the Tray every time there's a modification.
      if(IsTrayMinimized() && !Restoring)
      {
       // Because the cache can store additions, when there's a delete
       // operation, it first looks inside the cache.
       if(Operation == NIM_DELETE)
        for(int i = 0; i < ccount; i++)
         if(!cache[i].Empty)
          // If running in NT, the wide version of CINFO is used
          if(WinNT)
          {
           if(pInfoW->Data.hWnd == cache[i].InfoW.Data.hWnd)
            if(pInfoW->Data.uID == cache[i].InfoW.Data.uID)
             if(cache[i].InfoW.Operation == NIM_ADD)
             {
              cache[i].Empty = TRUE;
              if(cache[i].InfoW.Data.uFlags & NIF_ICON)
               DestroyIcon(cache[i].InfoW.Data.hIcon);
              // It returns to prevent the delete operation from -
              // reaching the original Taskbar WindowProc
              return 1;
             }
          }
          else
          {
           if(pInfo->Data.hWnd == cache[i].Info.Data.hWnd)
            if(pInfo->Data.uID == cache[i].Info.Data.uID)
             if(cache[i].Info.Operation == NIM_ADD)
             {
              cache[i].Empty = TRUE;
              if(cache[i].Info.Data.uFlags & NIF_ICON)
               DestroyIcon(cache[i].Info.Data.hIcon);
              // It returns to prevent the delete operation from -
              // reaching the original Taskbar WindowProc
              return 1;
             }
          }
       // It first searches for the system tray icon in the array
       for(int i = 0; i < ccount; i++)
        if(!cache[i].Empty)
         // If running in NT, the wide version of CINFO is used
         if(WinNT)
         {
          if(pInfoW->Data.hWnd == cache[i].InfoW.Data.hWnd)
           if(pInfoW->Data.uID == cache[i].InfoW.Data.uID)
           {
            if(Operation == NIM_ADD && cache[i].InfoW.Operation == NIM_DELETE)
            {
             Operation = NIM_MODIFY;
             cache[i].InfoW.Operation = Operation;
            }
            // It exits the loop
            break;
           }
         }
         else
         {
          if(pInfo->Data.hWnd == cache[i].Info.Data.hWnd)
           if(pInfo->Data.uID == cache[i].Info.Data.uID)
           {
            if(Operation == NIM_ADD && cache[i].Info.Operation == NIM_DELETE)
            {
             Operation = NIM_MODIFY;
             cache[i].Info.Operation = Operation;
            }
            // It exits the loop
            break;
           }
         }
 
       // If it didn't find the system tray icon in the array,
       // it searches the array for an empty item.
       if(i == ccount)
        for(int i = 0; i < 64; i++)
         if(cache[i].Empty)
          break;
 
       // If the array is full, it skips this part
       if(i < 64)
       {
        if(!cache[i].Empty)
        {
         if(WinNT)
         {
          if(pInfoW->Data.uFlags & NIF_ICON)
           DestroyIcon(cache[i].InfoW.Data.hIcon);
         }
         else
         {
          if(pInfo->Data.uFlags & NIF_ICON)
           DestroyIcon(cache[i].Info.Data.hIcon);
         }
        }
        cache[i].Empty = FALSE;
        cache[i].wParam = wParam;
        cache[i].hwnd = hwnd;
        cache[i].dwData = pData->dwData;
 
        // If it isn't a modification to the Tray, the whole data structure is copied
        if(Operation != NIM_MODIFY || i == ccount || cache[i].Empty)
        {
         if(WinNT)
         {
          cache[i].InfoW = *pInfoW;
          if(cache[i].InfoW.Data.uFlags & NIF_ICON)
           cache[i].InfoW.Data.hIcon = MyCopyIcon(pInfoW->Data.hIcon);
         }
         else
         {
          cache[i].Info = *pInfo;
          if(cache[i].Info.Data.uFlags & NIF_ICON)
           cache[i].Info.Data.hIcon = MyCopyIcon(pInfo->Data.hIcon);
         }
        }
        // Else only the modifications are copied
        else
        {
         if(WinNT)
         {
          if(pInfoW->Data.uFlags & NIF_ICON)
          {
           cache[i].InfoW.Data.uFlags |= NIF_ICON;
           cache[i].InfoW.Data.hIcon = MyCopyIcon(pInfoW->Data.hIcon);
          }
          if(pInfoW->Data.uFlags & NIF_MESSAGE)
          {
           cache[i].InfoW.Data.uFlags |= NIF_MESSAGE;
           cache[i].InfoW.Data.uCallbackMessage = pInfoW->Data.uCallbackMessage;
          }
          if(pInfoW->Data.uFlags & NIF_TIP)
          {
           cache[i].InfoW.Data.uFlags |= NIF_TIP;
           wcscpy(cache[i].InfoW.Data.szTip, pInfoW->Data.szTip);
          }
         }
         else
         {
          if(pInfo->Data.uFlags & NIF_ICON)
          {
           cache[i].Info.Data.uFlags |= NIF_ICON;
           cache[i].Info.Data.hIcon = MyCopyIcon(pInfo->Data.hIcon);
          }
          if(pInfo->Data.uFlags & NIF_MESSAGE)
          {
           cache[i].Info.Data.uFlags |= NIF_MESSAGE;
           cache[i].Info.Data.uCallbackMessage = pInfo->Data.uCallbackMessage;
          }
          if(pInfo->Data.uFlags & NIF_TIP)
          {
           cache[i].Info.Data.uFlags |= NIF_TIP;
           strcpy(cache[i].Info.Data.szTip, pInfo->Data.szTip);
          }
         }
        }
        if(i == ccount)
         ccount++;
        // It returns to prevent the cached message from reaching -
        // the original Taskbar WindowProc
        return 1;
       }
      }
      FlushCache();
      ClearRestoring = TRUE;
     }
  }
 
  // This user-defined message is used to end the subclassing
  else if(Message == EndSubclassing)
  {
   // It passes to the Tray any pending modifications.
   FlushCache();
   // It restores the original WindowProc
   SetWindowLong(hTaskbar, GWL_WNDPROC, (DWORD) OldProc);
  }
 
  // It checks if the tray needs hiding or restoring
  else if(Message == WM_SETCURSOR)
   HideRestoreTray();
 
  // It passes the message to the original Taskbar WindowProc
  int ret = CallWindowProc(OldProc, hwnd, Message, wParam, lParam);
  // It clears the Restoring flag if the tray was restored
  if(ClearRestoring)
  {
   ClearRestoring = FALSE;
   Restoring = FALSE;
  }
  return ret;
 }
 __except(1)
 {
  return 0;
 }
}
 
 
 
// The only purpose of this hook procedure is to enable -
// the replacement of the original Taskbar WindowProc.
LRESULT CALLBACK GetFunc(int nCode, WPARAM wParam, LPARAM lParam)
{
 __try
 {
  if(nCode == HC_ACTION)
  {
   LPMSG Msg = (LPMSG) lParam;
   // This is the user-defined message that's used to activate the subclassing
   if(Msg->message == BeginSubclassing)
    // It replaces the Taskbar WindowProc with it's own (TaskbarProc)
    OldProc = (WNDPROC)SetWindowLong(hTaskbar, GWL_WNDPROC, (DWORD) TaskbarProc);
  }
     return(CallNextHookEx(hGetHook, nCode, wParam, lParam));
 }
 __except(1)
 {
     return 0;
 }
}
 
 
 
// This is the implementation of the MouseProc used by the WH_MOUSE hook
LRESULT CALLBACK MouseFunc(int nCode, WPARAM wParam, LPARAM lParam)
{
 __try
 {
  if(nCode >= 0)
  {
   LPMOUSEHOOKSTRUCT Mouse = (LPMOUSEHOOKSTRUCT) lParam;
   switch(wParam)
   {
 
   // This message is processed to enable the click & drag feature
   case WM_LBUTTONDOWN:
    if(Mouse->wHitTestCode == HTCLIENT)
    {
     hWindow = Mouse->hwnd;
     // The following loop is used to search for the top-level parent window
     while(GetWindowLong(hWindow, GWL_STYLE) & WS_CHILDWINDOW)
      if(GetParent(hWindow) != GetDesktopWindow())
       hWindow = GetParent(hWindow);
      else
       break;
     if(hWindow != GetDesktopWindow())
      // The dragging feature is only available if the window isn't maximized
      if(!IsZoomed(hWindow))
      {
       // The LDown flag is used to indicate that the dragging feature has been started
       LDown = TRUE;
       PrevPos = Mouse->pt;
       // To enable the window dragging feature, the window -
       // original position is saved.
       GetWindowRect(hWindow, &WindowRect);
      }
    }
    break;
 
   case WM_MOUSEMOVE:
    // If the dragging feature has been started
    if(LDown)
     // If the Shift and Ctrl keys are pressed
     if ((GetAsyncKeyState(VK_SHIFT) & GetAsyncKeyState(VK_CONTROL)) >> 15)
     {
      // SwapMouseButton() is used to detect if the mouse is currently set -
      // for right-handed or left-handed use.
      BOOL Swapped = SwapMouseButton(TRUE);
      if((Swapped && GetAsyncKeyState(VK_RBUTTON) >> 15) || (!Swapped && GetAsyncKeyState(VK_LBUTTON) >> 15))
      {
       int x, y;
       x = WindowRect.left + Mouse->pt.x - PrevPos.x;
       y = WindowRect.top + Mouse->pt.y - PrevPos.y;
       // It moves the clicked window to its new position
       SetWindowPos(hWindow, 0, x, y, 0, 0, SWP_NOSIZE || SWP_NOZORDER);
      }
      SwapMouseButton(Swapped);
     }
     else
      LDown = FALSE;
 
    // It hides or restores the tray if necessary
    HideRestoreTray();
 
    break;
 
   case WM_LBUTTONUP:
    // When the user releases the left button, the LDown flag is cleared
    LDown = FALSE;
    break;
   }
  }
  // Always calls the next hook
     return(CallNextHookEx(hMouseHook, nCode, wParam, lParam));
 }
 __except(1)
 {
  return 0;
 }
}
 
 
 
// This function is called by TrayMagician.exe to install the necessary hooks
void CALLBACK HookInstall(HWND hwnd)
{
 WinNT = IsWinNT();
 hTrayMagic = hwnd;
 // It registers a unique message used to signal TrayMagician.exe -
 // that it should restore the system tray.
 RestoreMsg = RegisterWindowMessage("TrayMagician_RestoreTray");
 // These unique messages are used to initiate and end the subclassing of the Taskbar
 BeginSubclassing = RegisterWindowMessage("TrayMagician_BeginSubclassing");
 EndSubclassing = RegisterWindowMessage("TrayMagician_EndSubclassing");
 
 // First, several Taskbar windows are searched by their class name and their -
 // window handles are stored in global variables.
 hTaskbar = FindWindow("Shell_TrayWnd", NULL);
 hTray = FindWindowEx(hTaskbar, 0, "TrayNotifyWnd", NULL);
 hClock = FindWindowEx(hTray, 0, "TrayClockWClass", NULL);
 hReBar = FindWindowEx(hTaskbar, 0, "ReBarWindow32", NULL);
 hTaskSw = FindWindowEx(hTaskbar, 0, "MSTaskSwWClass", NULL);
 
 // This hook enables the window dragging feature and aids in the -
 // minimizing and restoring of the Tray.
 hMouseHook = SetWindowsHookEx(WH_MOUSE, MouseFunc, hInstance, 0);
 
 // This hook is used only to make possible the subclassing of the Taskbar
 hGetHook = SetWindowsHookEx(WH_GETMESSAGE, GetFunc, hInstance, GetWindowThreadProcessId(hTaskbar, NULL));
 // This is the user-defined message that is sent to activate the subclassing
 PostMessage(hTaskbar, BeginSubclassing, 0, 0);
}
 
 
 
// This function is called by TrayMagician.exe to remove all of the hooks
void CALLBACK HookRemove(void)
{
 // This user defined message is sent to restore the original
 // Taskbar WindowProc before removing the hooks.
 SendMessage(hTaskbar, EndSubclassing, 0, 0);
 
 UnhookWindowsHookEx(hMouseHook);
 UnhookWindowsHookEx(hGetHook);
}
 
 
 
// This function is called by TrayMagician.exe to update -
// the state of the Show Clock option.
void CALLBACK SetShowClock(BOOL Show)
{
 ShowClock = Show;
}