7.¹Ì´Ï ½ºÆÄÀÌ

°¡Àå ±âº»ÀûÀÎ ÇÁ·Î±×·¡¹Ö µµ±¸ÀÎ ½ºÆÄÀ̸¦ ºÐ¼®ÇØ º¸°í Àִµ¥ »ç¿ë ¹æ¹ýÀÌ ¿ö³« °£´ÜÇϰí Á÷°üÀûÀ̱⠶§¹®¿¡ Win32 API¿¡ ´ëÇÑ °³³äÀÌ ÀÖ´Ù¸é ÀÌ ÇÁ·Î±×·¥À» ÀÌÇØÇÏ°í »ç¿ëÇϴµ¥´Â º° ¾î·Á¿òÀÌ ¾øÀ» °ÍÀÌ´Ù. ±×·±µ¥ °³¹ßÀÚ ÀÔÀå¿¡¼­ Àú·± ÇÁ·Î±×·¥Àº °ú¿¬ ¾î¶»°Ô ¸¸µé±î ±Ã±ÝÇÑ »ý°¢ÀÌ µé±âµµ ÇÒ °ÍÀÌ´Ù. ¹º°¡ ´ë´ÜÇØ º¸ÀÌ°í ¾î·Á¿ö º¸ÀÌÁö¸¸ »ç½Ç ½ºÆÄÀÌ ¼öÁØÀÇ À¯Æ¿¸®Æ¼´Â ¾î·ÆÁö ¾Ê°Ô ¸¸µé ¼ö ÀÖ´Ù.

½ºÆÄÀÌ´Â ¸¶ÀÌÅ©·Î¼ÒÇÁÆ®»ç°¡ ºñÁÖ¾ó ½ºÆ©µð¿À¿Í ÇÔ²² ¹èÆ÷ÇÏ´Â À¯Æ¿¸®Æ¼ÀÌ¸ç ´©±¸³ª ÀÚÀ¯·Ó°Ô »ç¿ëÇÒ ¼ö ÀÖÀ» »Ó¸¸ ¾Æ´Ï¶ó ¼Ò½º±îÁö °ø°³µÇ¾î ÀÖ´Ù. MSDNÀÇ ¿¹Á¦Áß sdk/sdktools Æú´õ¸¦ º¸Æí spyÀÇ ¼Ò½º°¡ ÄÄÆÄÀÏ °¡´ÉÇÑ »óÅ·ΠÁ¦°øµÇ¹Ç·Î ½ºÆÄÀ̸¦ ¾î¶»°Ô ¸¸µé¾ú´ÂÁö ±Ã±ÝÇÏ´Ù¸é ÀÌ ¼Ò½º¸¦ ºÐ¼®ÇØ º¸±â ¹Ù¶õ´Ù. ³ª´Â ¼ÖÁ÷È÷ ÀÌ ¼Ò½º¸¦ ºÐ¼®ÇØ º» ÀûÀº ¾øÁö¸¸ ´ëÃæ ¾î¶»°Ô ¸¸µé¾ú´ÂÁö´Â ¾ÈºÁµµ ¾Ë ¼ö ÀÖÀ» °Í °°´Ù.

½ºÆÄÀÌÀÇ °¡Àå ÇÙ½ÉÀûÀÎ ±â´É µÎ°¡Áö¸¦ »Ì´Â´Ù¸é Ä¿¼­ ¾Æ·¡¿¡ ÀÖ´Â À©µµ¿ìÀÇ ¼Ó¼ºÀ» Á¶»çÇØ Áִ â ã±â ±â´É°ú ÀÌ Ã¢À¸·Î Àü´ÞµÇ´Â ¸Þ½ÃÁö¸¦ °¨½ÃÇÏ´Â ¸Þ½ÃÁö ºä ±â´ÉÀ» ²ÅÀ» ¼ö ÀÖ´Ù. ¸Þ½ÃÁö ºä´Â µð¹ö±ë¿¡ ¾ÆÁÖ °­·ÂÇÑ µµ±¸À̸ç â ã±â´Â ´Ù¸¥ ÇÁ·Î±×·¥ÀÇ ±¸Á¶¸¦ »ìÆì º¸´Â °¡Àå ±âº»ÀûÀÎ µµ±¸ÀÌ´Ù. ¿©±â¼­´Â ½ºÆÄÀÌÀÇ Ã¢ ã±â ±â´ÉÀ» Á» ´õ ¾²±â ½±°Ô ¸¸µç ¹Ì´Ï ½ºÆÄÀ̸¦ ¸¸µé¾î º¸µµ·Ï ÇÏÀÚ. ¼Ò½º´Â ´ÙÀ½°ú °°´Ù.

 

#include <windows.h>

#include "SHReg.h"

#include "resource.h"

 

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

HINSTANCE g_hInst;

HWND hWndMain;

LPSTR lpszClass="MiniSpy";

 

#define CAPWIDTH 15

#define WIDTH 300

#define HEIGHT 100

#define KEY "Software\\MiyoungSoft\\MiniSpy\\"

 

char szAbout[]="°¢Á¾ À©µµ¿ìÀÇ ¼Ó¼ºÀ» »ìÆìº¸´Â MiniSpyÀÔ´Ï´Ù\r\n"

   "¸¶¿ì½º Ä¿¼­¸¦ ¿øÇÏ´Â À©µµ¿ìÀ§¿¡ ¿Ã·Á µÎ½Ã¸é Ä¿¼­ ¾Æ·¡¿¡ "

   "ÀÖ´Â À©µµ¿ìÀÇ ¼Ó¼ºµéÀ» Á¶»çÇØ¼­ º¸¿©ÁÝ´Ï´Ù.";

int bTop;

HWND hWndOld;

char str[1024];

HFONT font;

BOOL bCloseDown;

 

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance

     ,LPSTR lpszCmdParam,int nCmdShow)

{

   HWND hWnd;

   MSG Message;

   WNDCLASS WndClass;

   g_hInst=hInstance;

  

   WndClass.cbClsExtra=0;

   WndClass.cbWndExtra=0;

   WndClass.hbrBackground=(HBRUSH)(COLOR_BTNFACE+1);

   WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);

   WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);

   WndClass.hInstance=hInstance;

   WndClass.lpfnWndProc=(WNDPROC)WndProc;

   WndClass.lpszClassName=lpszClass;

   WndClass.lpszMenuName=NULL;

   WndClass.style=CS_HREDRAW | CS_VREDRAW;

   RegisterClass(&WndClass);

 

   hWnd=CreateWindowEx(WS_EX_TOPMOST,lpszClass,lpszClass,WS_POPUP,

      CW_USEDEFAULT,CW_USEDEFAULT,WIDTH,HEIGHT,

      NULL,(HMENU)NULL,hInstance,NULL);

   ShowWindow(hWnd,nCmdShow);

   hWndMain=hWnd;

  

   while(GetMessage(&Message,0,0,0)) {

      TranslateMessage(&Message);

      DispatchMessage(&Message);

   }

   return Message.wParam;

}

 

// À©µµ¿ì ¼Ó¼ºÀ» ¹®ÀÚ¿­ ÇüÅ·ΠÁ¶¸³ÇÑ´Ù. WS_´Â »ý·«ÇÏ¿´´Ù.

#define TEST(n) (dwStyle & (1 << n))

void GetStyleString(DWORD dwStyle, char *sStyle)

{

   if (TEST(31)) strcpy(sStyle,"POPUP");

   else if (TEST(30)) strcpy(sStyle,"CHILD");

   else strcpy(sStyle,"OVERLAPPED");

 

   if (TEST(29)) strcat(sStyle," | MINIMIZE");

   if (TEST(28)) strcat(sStyle," | VISIBLE");

   if (TEST(27)) strcat(sStyle," | DISABLED");

   if (TEST(26)) strcat(sStyle," | CLIPSIBLINGS");

   if (TEST(25)) strcat(sStyle," | CLIPCHILDREN");

   if (TEST(24)) strcat(sStyle," | MAXIMIZE");

   if (TEST(23)) strcat(sStyle," | BORDER");

   if (TEST(22)) strcat(sStyle," | DLGFRAME");

   if (TEST(21)) strcat(sStyle," | VSCROLL");

   if (TEST(20)) strcat(sStyle," | HSCROLL");

   if (TEST(19)) strcat(sStyle," | SYSMENU");

   if (TEST(18)) strcat(sStyle," | THICKFRAME");

   if (TEST(17)) strcat(sStyle," | MINIMIZEBOX");

   if (TEST(16)) strcat(sStyle," | MAXIMIZEBOX");

}

 

BOOL CALLBACK AboutDlgProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

   switch(iMessage)

   {

   case WM_INITDIALOG:

      return TRUE;

   case WM_COMMAND:

      switch (wParam)

      {

      case IDOK:

      case IDCANCEL:

          EndDialog(hDlg,0);

          return TRUE;

      }

      break;

   }

   return FALSE;

}

 

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

   HDC hdc;

   PAINTSTRUCT ps;

   POINT pt;

   HWND hWndPoint, hWndParent;

   char sCaption[256], sClass[256];

   RECT crt;

   UINT nHit;

   HFONT oldfont;

   HRGN hWndRgn;

   HMENU hMenu, hPopup;

   DWORD dwStyle;

   char sStyle[256];

 

   switch(iMessage) {

   case WM_CREATE:

      hWndRgn=CreateRoundRectRgn(0,0,WIDTH,HEIGHT,20,20);

      SetWindowRgn(hWnd,hWndRgn,FALSE);

      SetTimer(hWnd,1,500,NULL);

      font=CreateFont(12,0,0,0,0,0,0,0,HANGEUL_CHARSET,3,2,1,

          VARIABLE_PITCH | FF_MODERN,"±¼¸²");

      // ÃÖÈÄ ½ÇÇà À§Ä¡·Î À̵¿ÇÑ´Ù.

      crt.left=SHRegReadInt(SHCU,KEY"Pos","X",0);

      crt.top=SHRegReadInt(SHCU,KEY"Pos","Y",0);

      bTop=SHRegReadInt(SHCU,KEY"Pos","Top",1);

      SetWindowPos(hWnd,(bTop ? HWND_TOPMOST:HWND_NOTOPMOST),

          crt.left,crt.top,0,0,SWP_NOSIZE);

      return 0;

   case WM_TIMER:

      GetCursorPos(&pt);

      hWndPoint=WindowFromPoint(pt);

      if (hWndPoint == hWndOld)

          return 0;

      hWndOld=hWndPoint;

      if (hWndPoint == NULL) {

          strcpy(str,"À©µµ¿ì ¾øÀ½");

      } else if (hWndPoint == hWnd) {

          strcpy(str,szAbout);

      } else {

         GetWindowText(hWndPoint,sCaption,256);

          GetClassName(hWndPoint,sClass,256);

          hWndParent=GetParent(hWndPoint);

          GetWindowRect(hWndPoint,&crt);

          dwStyle=GetWindowLong(hWndPoint,GWL_STYLE);

          GetStyleString(dwStyle,sStyle);

          wsprintf(str,

             "ÇÚµé : %d(0x%x)\r\n"

             "Ŭ·¡½º : %s\r\n"

             "ĸ¼Ç : %s\r\n"

             "ºÎ¸ð : %d(0x%x)\r\n"

             "¿µ¿ª : (%d,%d) - (%d,%d), %d*%d\r\n"

             "½ºÅ¸ÀÏ : %X(%s)",

             hWndPoint,hWndPoint,sClass,sCaption,hWndParent,hWndParent,

             crt.left, crt.top, crt.right, crt.bottom, crt.right-crt.left,

             crt.bottom-crt.top,dwStyle,sStyle);

      }

      InvalidateRect(hWnd,NULL,TRUE);

      return 0;

   case WM_PAINT:

      hdc=BeginPaint(hWnd, &ps);

 

      RoundRect(hdc,0,0,WIDTH-1,HEIGHT-1,20,20);

      // ¿ÞÂÊ¿¡ ŸÀÌÆ² ¹Ù¸¦ ±×¸°´Ù.

      GetClientRect(hWnd,&crt);

      crt.right=CAPWIDTH;

      FillRect(hdc,&crt,GetSysColorBrush(COLOR_ACTIVECAPTION));

 

      // Á¾·á ¹öưÀ» ±×¸°´Ù.

      Rectangle(hdc,1,5,13,17);

      MoveToEx(hdc,4,8,NULL);LineTo(hdc,10,14);

      MoveToEx(hdc,10,8,NULL);LineTo(hdc,4,14);

 

      // Á¤º¸¸¦ Ãâ·ÂÇÑ´Ù.

      GetClientRect(hWnd,&crt);

      crt.left+=CAPWIDTH+2;

      crt.top+=2;

      SetBkMode(hdc,TRANSPARENT);

      oldfont=(HFONT)SelectObject(hdc,font);

      DrawText(hdc,str,-1,&crt,DT_WORDBREAK);

      SelectObject(hdc,oldfont);

      EndPaint(hWnd, &ps);

      return 0;

   case WM_LBUTTONDOWN:

      pt.x=LOWORD(lParam);

      pt.y=HIWORD(lParam);

      if ((pt.x > 1) && (pt.x < 13) && (pt.y > 5) && (pt.y < 17)) {

          bCloseDown=TRUE;

      } else {

          bCloseDown=FALSE;

      }

      return 0;

   case WM_LBUTTONUP:

      pt.x=LOWORD(lParam);

      pt.y=HIWORD(lParam);

      if ((bCloseDown==TRUE) && (pt.x > 1) && (pt.x < 13)

          && (pt.y > 5) && (pt.y < 17)) {

          DestroyWindow(hWnd);

      }

      return 0;

   case WM_NCHITTEST:

      nHit=DefWindowProc(hWnd,iMessage,wParam,lParam);

      pt.x=LOWORD(lParam);

      pt.y=HIWORD(lParam);

      ScreenToClient(hWnd,&pt);

      if ((nHit==HTCLIENT) && (pt.x <= CAPWIDTH) && (pt.y > 15))

          nHit=HTCAPTION;

      return nHit;

   case WM_CONTEXTMENU:

      hMenu=LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU1));

      hPopup=GetSubMenu(hMenu, 0);

 

      if (bTop==TRUE)

          CheckMenuItem(hPopup, IDM_TOP, MF_BYCOMMAND | MF_CHECKED);

 

      TrackPopupMenu(hPopup, TPM_LEFTALIGN, LOWORD(lParam), HIWORD(lParam),

          0, hWnd, NULL);

      DestroyMenu(hMenu);

      return 0;

   case WM_COMMAND:

      switch(LOWORD(wParam)) {

      case IDM_EXIT:

          DestroyWindow(hWnd);

          break;

      case IDM_TOP:

          bTop=!bTop;

          SetWindowPos(hWnd,(bTop ? HWND_TOPMOST:HWND_NOTOPMOST)

             ,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

          break;

      case IDM_ABOUT:

          DialogBox(g_hInst,MAKEINTRESOURCE(IDD_DIALOG1),hWnd,AboutDlgProc);

          break;

      }

      return 0;

   case WM_DESTROY:

      DeleteObject(font);

      // ¸¶Áö¸· À§Ä¡¸¦ ÀúÀåÇØµÐ´Ù.

      GetWindowRect(hWnd,&crt);

      SHRegWriteInt(SHCU,KEY"Pos","X",crt.left);

      SHRegWriteInt(SHCU,KEY"Pos","Y",crt.top);

      SHRegWriteInt(SHCU,KEY"Pos","Top",bTop);

      PostQuitMessage(0);

      return 0;

   }

   return(DefWindowProc(hWnd,iMessage,wParam,lParam));

}

 

º¸´Ù½ÃÇÇ º°·Î ±æÁöµµ ¾Ê°í Áß°£ Áß°£¿¡ ÁÖ¼®±îÁö ÀÖÀ¸¹Ç·Î µû·Î ºÐ¼®ÇØ º¼ ÇÊ¿ä±îÁö´Â ¾øÀ» °Í °°´Ù. ÀÌ ¿¹Á¦ÀÇ ÇÙ½É ÇÔ¼ö´Â WM_TIMER¿¡ ÀÖ´Â WindowFromPointÀε¥ ÀÌ ÇÔ¼ö´Â ÁöÁ¤ÇÑ ÁÂÇ¥¿¡ ÀÖ´Â À©µµ¿ìÀÇ ÇÚµéÀ» ±¸ÇØ ÁØ´Ù. À©µµ¿ì Çڵ鸸 ±¸Çϸé ÁÂÇ¥ Á¶»ç³ª ¼Ó¼º Á¶»ç´Â ½ÄÀº Á׸ԱâÀ̹ǷΠ³ª¸ÓÁö ÀÛ¾÷Àº ÀÌ ÇÚµé·ÎºÎÅÍ ±¸ÇÑ Á¤º¸¸¦ Àß °¡°øÇÏ¿© Àб⠽±°Ô Ãâ·ÂÇØ ÁÖ´Â °Í »ÓÀÌ´Ù. À©µµ¿ì ÇÚµé°ú Ŭ·¡½º À̸§À» Á¶»çÇϰí Á¤¼öÇüÀ¸·Î µÇ¾î ÀÖ´Â ½ºÅ¸ÀÏÀÇ ½ÇÁ¦ Àǹ̸¦ ¹®ÀÚ¿­·Î Ç®¾î¼­ Ãâ·ÂÇÏ¿´´Ù.

À©µµ¿ì ¸ð¾çÀÌ Á¤ »ç°¢ÇüÀÌ ¾Æ´Ñ µÕ±Ù »ç°¢ÇüÀ¸·Î µÇ¾î ÀÖ°í °¡±ÞÀûÀ̸é È­¸é ¿µ¿ªÀ» ÀÛ°Ô Â÷ÁöÇϵµ·Ï Çϱâ À§ÇØ Å¸ÀÌÆ² ¹Ù¸¦ ¿ÞÂÊ º¯¿¡ Á¶±×¸Ä°Ô º°µµ·Î ¸¸µé¾î µÎ¾ú´Ù. ÀÌ·± ±â±³¿¡ °ü½ÉÀÌ ÀÖ´Ù¸é ÀÌ ¿¹Á¦°¡ µµ¿òÀÌ µÉ °ÍÀÌ´Ù. µÕ±Ù »ç°¢Çü ÇüÅÂÀÇ À©µµ¿ì¸¦ ¸¸µå´Â ÇÙ½É ÇÔ¼ö´Â SetWindowRgnÀ̸ç Ä¿½ºÅÒ Å¸ÀÌÆ² ¹Ù¸¦ ó¸®ÇÏ´Â ÇÙ½É ÄÚµå´Â WM_NCHITTEST¿¡ ÀÖÀ¸¹Ç·Î ºÐ¼®ÇØ º¸±â ¹Ù¶õ´Ù. ½ÇÇàÁßÀÇ ¸ð½ÀÀº ´ÙÀ½°ú °°´Ù.

ŸÀÌÆ² ¹Ù À§ÂÊ¿¡ ´Ý±â ¹öưÀÌ ÀÖÀ¸¸ç ÆË¾÷ ¸Þ´º¿¡¼­ 'Ç×»ó À§' ¿É¼ÇÀ» ¼±ÅÃÇÒ ¼ö ÀÖ´Ù. º°µµÀÇ ¸í·É¾øÀÌ ½ÇÇà½ÃÄÑ ³õ°í Ä¿¼­¸¸ °¡Á® °¡¸é ÇØ´ç À©µµ¿ìÀÇ Á¤º¸¸¦ °£´ÜÇÏ°Ô »ìÆìº¼ ¼ö ÀÖ´Ù. ƯÈ÷ ¸Þ´º³ª ½Ã½ºÅÛ ¸ð´Þ°°ÀÌ ½ºÆÄÀÌ·Î µµÀúÈ÷ Âï¾îº¼ ¼ö ¾ø´Â °Í±îÁöµµ º¼ ¼ö ÀÖ´Ù´Â °ÍÀÌ ÀåÁ¡ÀÌ´Ù. ÀÌ ¿¹Á¦ÀÇ ¼Ò½º´Â http://www.winapi.co.kr/book/download/MiniSpySrc.zip¿¡ ÀÖ´Ù.