티스토리 툴바

블로그 이미지

Passion of ComputerScience

Team Blog For Soft Engineering Team Project Manager : Park, Choi, Jeon Project Name : Linkube (Link + cube) "Passion is survival, not death." by cocy


'Gathering_Information'에 해당되는 글 8건

  1. 2008/12/15 [api-스크랩] FindFirstFile
  2. 2008/12/12 [api-디렉토리탐색-스크랩]about). FindFirstFile(), FindNextFile(), FindClose()
  3. 2008/12/07 [스크랩 - WIN32 API ] 분할 윈도우 만들기
  4. 2008/12/07 [스크랩] Win32 API 비트맵 회전 함수 전체 소스 코드
  5. 2008/11/12 [LINKUBE-SCRIPT] IWebBrowser2
  6. 2008/11/07 [이것이 리얼 윈도우] wii리모컨으로 구현한 시선추적 시스템
  7. 2008/10/29 API 팁들 모음
  8. 2008/10/12 꿀뷰3 제작자 인터뷰

[api-스크랩] FindFirstFile


Console과 API의 경우에는 FindFirstFile과 FindNextFile을 이용하실 수 있습니다.

FindFirstFile의 원형은 다음과 같습니다.

HANDLE FindFirstFile(
  LPCTSTR
lpFileName // pointer to name of file to search for
  LPWIN32_FIND_DATA lpFindFileData
                       // pointer to returned information
);

 

lpFileName : 파일 검색을 위한 파일 이름. "c\\*.*"또는 "c:\\*.txt" 같은 형식을 지정할 수 있다.

lpFindFileData : 파일 검색용 데이터 구조체다. 검색된 파일들의 정보가 담겨진다.

 

두번째로 FindNextFile의 원형은 다음과 같습니다.

 

BOOL FindNextFile(
  HANDLE hFindFile,
  LPWIN32_FIND_DATA lpFindFileData
);

hFindFile : FindFirstFile이 넘겨준 핸들을 넣는다. 실제 검색용 스레드가 돌고 있는 핸들이다.

lpFindFileData : 파일 검색용 구조체. FindFirstFile이 넘겨준 구조체를 주면 된다.

 

세번째로 그 파일의 정보를 담는 WIN32_FIND_DATA입니다.

 

typedef struct _WIN32_FIND_DATA {
  DWORD dwFileAttributes;
  FILETIME ftCreationTime;
  FILETIME ftLastAccessTime;
  FILETIME ftLastWriteTime;
  DWORD nFileSizeHigh;
  DWORD nFileSizeLow;
  DWORD dwReserved0;
  DWORD dwReserved1;
  TCHAR cFileName[MAX_PATH];
  TCHAR cAlternateFileName[14];
} WIN32_FIND_DATA,
*PWIN32_FIND_DATA;

 

 

위의 두 함수를 조합하여 사용 할 수 있습니다.

 

아래는 MSDN에서 제공하는 예제소스입니다.

 

#define _WIN32_WINNT 0x0501

#include <windows.h>
#include <string.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
   WIN32_FIND_DATA FindFileData;
   HANDLE hFind = INVALID_HANDLE_VALUE;
   char DirSpec[MAX_PATH];  // directory specification
   DWORD dwError;

   printf ("Target directory is %s.\n", argv[1]);
   strncpy (DirSpec, argv[1], strlen(argv[1])+1);
   strncat (DirSpec, "\\*", 3);

   hFind = FindFirstFile(DirSpec, &FindFileData);

   if (hFind == INVALID_HANDLE_VALUE) 
   {
      printf ("Invalid file handle. Error is %u\n", GetLastError());
      return (-1);
   } 
   else 
   {
      printf ("First file name is %s\n", FindFileData.cFileName);
      while (FindNextFile(hFind, &FindFileData) != 0) 
      {
         printf ("Next file name is %s\n", FindFileData.cFileName);
      }
    
      dwError = GetLastError();
      FindClose(hFind);
      if (dwError != ERROR_NO_MORE_FILES) 
      {
         printf ("FindNextFile error. Error is %u\n", dwError);
         return (-1);
      }
   }
   return (0);
}

소스는 간단합니다. FindFirstFile함수를 통해 디렉토리의 지정및 그 디렉토리의
가장 처음 파일을 찾습니다.
그후 FindNextFile을 통해 다음 파일들을 일일이 찾아서 검색조건에 일치한다면
TRUE를 리턴하는 것입니다.
WIN32_FIND_DATA 구조체에는 파일의 서치 정보가 들어있습니다. 파일의 속성및
파일이름, 생성날짜, 크기 등등 거의 모든 정보가 들어있습니다. 이를 활용하여
파일의 변경여부등도 파악이 가능합니다.
Comment 0 Trackback 0

Trackback : http://sepoc.tistory.com/trackback/51 관련글 쓰기

Top

[api-디렉토리탐색-스크랩]about). FindFirstFile(), FindNextFile(), FindClose()


FindFirstFile(), FindNextFile(), FindClose()
 
특정 디렉토리 아래에 있는 모든 파일과 서브 디렉토리 혹은 특정 조건의 파일과 서브 디렉토리를 얻을 때
사용하는 API함수
 
FindFirstFile()
 - 원형 : HANDLE FindFirstFile(LPCTSTR lpFileNameLPWIN32_FIND_DATA lpFindFileData);
 - 파라미터
   . lpFileName : 특정한 경로나 디렉토리 또는 (*) 또는 (?) 를 포함한 wildcard character 파일명을
                      지정할 수 있다.
   . lpFindFileData : WIN32_FIND_DATA 구조체에 찾은 파일 또는 서브 디렉토리의 정보를 담는다.
 - 리턴
   . 호출 성공 : search handle을 리턴
   . 호출 실패 : INVALID_HANDLE_VALUE를 리턴. 확장된 에러 정보를 얻기위해서 GetLastError()를 호출
 - 설명
   .파일 검색을 시작한다.
 
FindClose()
 - 원형 : BOOL FindClose( HANDLE hFindFile );
 - 파라미터
   . hFindFile : FindFirstFile()을 통해서 얻은 search 핸들
 - 설명 : FindFirstFile() 또는 FindFirstFileEx() 에 의해 얻은 파일 핸들을 닫는다.
 
FindNextFile()
 - 원형 : BOOL FindNextFile(HANDLE hFindFileLPWIN32_FIND_DATA lpFindFileData );
 - 파라미터
   . hFindFile : FindFirstFile() 또는 FindFirstFileEx() 에 의해 얻은 핸들
   . lpFindFileData : WIN32_FIND_DATA 구조체에 찾은 파일 또는 서브 디렉토리의 정보를 담는다.
 - 리턴
   . 호출 성공 : 0이 아닌 값을 리턴
   . 호출 실패 : 0을 리턴. 더 많은 에러 정보를 얻기 위해서 GetLastError() 호출
 - 설명
   .  다음 파일의 정보를 얻는다.
 
WIN32_FIND_DATA
 - FindFirstFile, FindFirstFileEx, FindNextFile 등의 함수로 얻은 정보를 담은 구조체.
 - 자세한 정보
 
GetLassError
 - 원형 : DWORD GetLastError(void);
 - 파라미터
   . 없음
 - 리턴
   . Calling Thread의 마지막 에러 코드를 리턴한다.
 - 설명 : Calling Thread의 마지막 에러를 받는다.
 - 자세한 정보
 
System Error Code
Comment 0 Trackback 0

Trackback : http://sepoc.tistory.com/trackback/49 관련글 쓰기

Top

[스크랩 - WIN32 API ] 분할 윈도우 만들기


WIN 32 API를 이용해서 분할윈도우를 만들고자 2일에 걸쳐서 인터넷를 뒤졌죠..

그러다가 어떤님 블로그에서 비슷한 예제를 발견했네요. 하지만; 실행이 안되더군요..ㅠ_ㅠ

그래도 그걸 참고삼아서 이러저리 짜집기를 해놓았드니 돌아가드라구요.. 넘 어렵게 찾아서 팁으로 올려봅니다.

아무쪼록 도움이 되는 분들이 있기를^^   시작합니다.

 

===================================================================================================================

저는 VC2005를 사용합니다. 그걸 위주로 설명할께요.

 

먼저 프로젝트를 생성합니다.  WIN32 Project의 Windows Application 스타일로 만들면 됩니다.

프로젝트가 생성이 되면 기본적인 stdafx파일과 메인윈도우가 자동으로 생성이 됩니다.^^

 

그러면 만들어진 자동생성 코드에 보면

 

 ATOM MyRegisterClass(HINSTANCE hInstance)

{

WNDCLASSEX wcex;

<----브러쉬 관련 코드 넣기----->

 wcex.cbSize = sizeof(WNDCLASSEX);

 wcex.style   = CS_HREDRAW | CS_VREDRAW;
 wcex.lpfnWndProc = WndProc;
 wcex.cbClsExtra  = 0;
 wcex.cbWndExtra  = 0;
 wcex.hInstance  = hInstance;
 wcex.hIcon   = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TEST2));
 wcex.hCursor  = LoadCursor(NULL, IDC_ARROW);
 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TEST2);
 wcex.lpszClassName = szWindowClass;
 wcex.hIconSm  = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

 

<----분할 윈도우 관련 코드 넣기----->

 

return RegisterClassEx(&wcex);

}

 

클래스가 있습니다. 위와 같은 형태입니다. 위의 클래스에 분할될 윈도우에 관한 설정을 추가해 줘야 합니다.

위의 코드에서 <브러쉬 관련 코드넣기 >부분에 아래 코드를 추가합니다. 분할된 윈도우에 색을 넣어주기 위해서 입니다. 그래야 눈에 잘 띄어서 제대로 들어갓는지 확인하기가 편하거든요.

 

static HBRUSH hRedBrush,  hBlueBrush,  hGreenBrush;
 hRedBrush=CreateSolidBrush(RGB(255,0,0));
 hGreenBrush=CreateSolidBrush(RGB(0,255,0));
 hBlueBrush=CreateSolidBrush(RGB(0,0,255));

 

 다음으로 아래의 <분할 윈도우 관련 코드 넣기> 부분에 아래 코드를 삽입합니다.

hbrBcakground 는 윈도우에 색을 넣는 부분입니다. 빨랑, 초록, 파랑 순으로 넣을겁니다.

lpfnWndProc 는 윈도우 프로시저를 링크합니다. 메시지들을 받기 위해서죠.

lpszClassName 는 클래스의 이름을 넣는 부분입니다.

 

wcex.hbrBackground = hRedBrush;
wcex.lpfnWndProc = ChildLeftProc;
wcex.lpszClassName = "ChildLeft";
RegisterClassEx(&wcex);

 

wcex.hbrBackground = hGreenBrush;
 wcex.lpfnWndProc = ChildTopProc;
 wcex.lpszClassName = "ChildTop";
 RegisterClassEx(&wcex);

 

 wcex.hbrBackground = hBlueBrush;
 wcex.lpfnWndProc = ChildBottomProc;
 wcex.lpszClassName = "ChildBottom";

 

 

 

자 그럼 MyRegisterClass() 함수에 관해서는 끝났습니다.

다음으로 위에 ChildLeftProc, ChildTopProc, ChildBottomPorc 클래스가 없습니다. 이부분은

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

클래스를 복사하셔서 적당하게 만드시기 바랍니다. 위에 선언해 주시는 것도 잊지 마시고요.

 

 

그럼 이제 윈도우 생성함수를 만들어야 됩니다.

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

 이 프로시저 함수 안에 만들겁니다.

 

case WM_CREATE:
  hC1 = CreateWindow("ChildLeft", NULL, WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN|, 0, 0, 0, 0, hWnd, 0, hInst, NULL);  
  hC2 = CreateWindow("ChildTop", NULL, WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN, 0, 0, 0, 0, hWnd, 0, hInst, NULL);

  hC3 = CreateWindow("ChildBottom", NULL, WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN, 0, 0, 0, 0, hWnd, 0, hInst, NULL);

break;

 

switch문 안에 위의 코드를 삽입합니다. 윈도우를 생성하는 함수입니다. 3개의 윈도우로 나눌것이기 때문에 3개를 만들었습니다. 주의할 점은 먼 처음 인자에 "ChildLeft"부분을 위에서 클래스이름과 동일하게 해야 된다는 점입니다.

 

다음으로 3개의 윈도우의 위치를 설정합니다. MoveWindow()를 사용합니다. 코드는 아래와 같습니다.

 

case WM_SIZE:
  if(wParam != SIZE_MINIMIZED)
  {
   GetClientRect(hWnd, &rect);
   MoveWindow(hC1, 0, 0, 300, 300, TRUE);
   MoveWindow(hC2, 300, 0, rect.right-300, 300, TRUE);
   MoveWindow(hC3, 0, 300, rect.right, rect.bottom, TRUE);
  }
  break;

 

 

 실행하면 아래와 같이 됩니다.

 

 

 

 



// TEST2.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "TEST2.h"

#define MAX_LOADSTRING 100

 

//윈도우 핸들 추가

HWND hC1, hC2, hC3;


// Global Variables:
HINSTANCE hInst;        // current instance
TCHAR szTitle[MAX_LOADSTRING];     // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];   // the main window class name

// Forward declarations of functions included in this code module:
ATOM    MyRegisterClass(HINSTANCE hInstance);
BOOL    InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);

 

//윈도우 프로시저 추가

LRESULT CALLBACK ChildLeftProc(HWND,UINT,WPARAM,LPARAM);
LRESULT CALLBACK ChildTopProc(HWND,UINT,WPARAM,LPARAM);
LRESULT CALLBACK ChildBottomProc(HWND,UINT,WPARAM,LPARAM
);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
 UNREFERENCED_PARAMETER(hPrevInstance);
 UNREFERENCED_PARAMETER(lpCmdLine);

  // TODO: Place code here.
 MSG msg;
 HACCEL hAccelTable;

 // Initialize global strings
 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
 LoadString(hInstance, IDC_TEST2, szWindowClass, MAX_LOADSTRING);
 MyRegisterClass(hInstance);

 // Perform application initialization:
 if (!InitInstance (hInstance, nCmdShow))
 {
  return FALSE;
 }

 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TEST2));

 // Main message loop:
 while (GetMessage(&msg, NULL, 0, 0))
 {
  if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
  {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
 }

 return (int) msg.wParam;
}

 

//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
 WNDCLASSEX wcex;

//브러시 추가
 static HBRUSH hRedBrush,hBlueBrush,hGreenBrush;
 hRedBrush=CreateSolidBrush(RGB(255,0,0));
 hGreenBrush=CreateSolidBrush(RGB(0,255,0));
 hBlueBrush=CreateSolidBrush(RGB(0,0,255));


 wcex.cbSize = sizeof(WNDCLASSEX);

 wcex.style   = CS_HREDRAW | CS_VREDRAW;
 wcex.lpfnWndProc = WndProc;
 wcex.cbClsExtra  = 0;
 wcex.cbWndExtra  = 0;
 wcex.hInstance  = hInstance;
 wcex.hIcon   = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TEST2));
 wcex.hCursor  = LoadCursor(NULL, IDC_ARROW);
 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TEST2);
 wcex.lpszClassName = szWindowClass;
 wcex.hIconSm  = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

 RegisterClassEx(&wcex);

 

//윈도우 클래스 설정

 wcex.hbrBackground = hRedBrush;
 wcex.lpfnWndProc = ChildLeftProc;
 wcex.lpszClassName = "ChildLeft";
 RegisterClassEx(&wcex);

 

 wcex.hbrBackground = hGreenBrush;
 wcex.lpfnWndProc = ChildTopProc;
 wcex.lpszClassName = "ChildTop";
 RegisterClassEx(&wcex);

 

 wcex.hbrBackground = hBlueBrush;
 wcex.lpfnWndProc = ChildBottomProc;
 wcex.lpszClassName = "ChildBottom";

 

 return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

 

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND - process the application menu
//  WM_PAINT - Paint the main window
//  WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 int wmId, wmEvent;
 PAINTSTRUCT ps;
 HDC hdc;
 RECT rect;

 switch (message)
 {
 case WM_COMMAND:
  wmId    = LOWORD(wParam);
  wmEvent = HIWORD(wParam);
  // Parse the menu selections:
  switch (wmId)
  {
  case IDM_ABOUT:
   DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
   break;
  case IDM_EXIT:
   DestroyWindow(hWnd);
   break;
  default:
   return DefWindowProc(hWnd, message, wParam, lParam);
  }
  break;
 case WM_CREATE:

 

//윈도우 생성
  hC1 = CreateWindow("ChildLeft", NULL, WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN, 0, 0, 0, 0, hWnd, 0, hInst, NULL);  
  hC2 = CreateWindow("ChildTop", NULL, WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN, 0, 0, 0, 0, hWnd, 0, hInst, NULL);
  hC3 = CreateWindow("ChildBottom", NULL, WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN, 0, 0, 0, 0, hWnd, 0, hInst, NULL);
  
  
  break;
 case WM_SIZE:

//윈도우 위치, 사이즈 조정
  if(wParam != SIZE_MINIMIZED)
  {
   GetClientRect(hWnd, &rect);
   MoveWindow(hC1, 0, 0, 300, 300, TRUE);
   MoveWindow(hC2, 300, 0, rect.right-300, 300, TRUE);
   MoveWindow(hC3, 0, 300, rect.right, rect.bottom, TRUE);
  }

  break;
 case WM_PAINT:
  hdc = BeginPaint(hWnd, &ps);
  // TODO: Add any drawing code here...
  EndPaint(hWnd, &ps);
  break;
 case WM_DESTROY:
  PostQuitMessage(0);
  break;
 default:
  return DefWindowProc(hWnd, message, wParam, lParam);
 }
 return 0;
}


// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
 UNREFERENCED_PARAMETER(lParam);
 switch (message)
 {
 case WM_INITDIALOG:
  return (INT_PTR)TRUE;
 
 case WM_COMMAND:
  if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
  {
   EndDialog(hDlg, LOWORD(wParam));
   return (INT_PTR)TRUE;
  }
  break;
 }
 return (INT_PTR)FALSE;
}


LRESULT CALLBACK ChildLeftProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 int wmId, wmEvent;
 PAINTSTRUCT ps;
 HDC hdc;

 switch (message)
 {
 case WM_COMMAND:
  wmId    = LOWORD(wParam);
  wmEvent = HIWORD(wParam);
  // Parse the menu selections:
  
  break;
 
 case WM_PAINT:
  hdc = BeginPaint(hWnd, &ps);
  // TODO: Add any drawing code here...
  EndPaint(hWnd, &ps);
  break;
 case WM_DESTROY:
  PostQuitMessage(0);
  break;
 default:
  return DefWindowProc(hWnd, message, wParam, lParam);
 }
 return 0;
}


LRESULT CALLBACK ChildTopProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 int wmId, wmEvent;
 PAINTSTRUCT ps;
 HDC hdc;

 switch (message)
 {
 case WM_COMMAND:
  wmId    = LOWORD(wParam);
  wmEvent = HIWORD(wParam);
  // Parse the menu selections:
  
  break; 
 case WM_PAINT:
  hdc = BeginPaint(hWnd, &ps);
  // TODO: Add any drawing code here...
  EndPaint(hWnd, &ps);
  break;
 case WM_DESTROY:
  PostQuitMessage(0);
  break;
 default:
  return DefWindowProc(hWnd, message, wParam, lParam);
 }
 return 0;
}


LRESULT CALLBACK ChildBottomProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 int wmId, wmEvent;
 PAINTSTRUCT ps;
 HDC hdc;

 switch (message)
 {
 case WM_COMMAND:
  wmId    = LOWORD(wParam);
  wmEvent = HIWORD(wParam);
  // Parse the menu selections:
  
  break;
 case WM_PAINT:
  hdc = BeginPaint(hWnd, &ps);
  // TODO: Add any drawing code here...
  EndPaint(hWnd, &ps);
  break;
 case WM_DESTROY:
  PostQuitMessage(0);
  break;
 default:
  return DefWindowProc(hWnd, message, wParam, lParam);
 }
 return 0;
}

Comment 0 Trackback 0

Trackback : http://sepoc.tistory.com/trackback/48 관련글 쓰기

Top

[스크랩] Win32 API 비트맵 회전 함수 전체 소스 코드


  1. #include <windows.h>   
  2. #include <math.h>   
  3.   
  4. #define PI          3.141592654   
  5.   
  6. // 인수목록   
  7. // HDC      hdc         :   
  8. // HBITMAP  hBitmap     :   
  9. // int      source_x    : 회전 이미지 비트맵에서의, 출력할 사각영역의 좌상단x좌표.   
  10. // int      source_y    : 회전 이미지 비트맵에서의, 출력할 사각영역의 좌상단y좌표.   
  11. // int      dest_width  : 회전할 비트맵 이미지의 폭   크기 == 회전할 비트맵 이미지가 출력될 폭 크기   
  12. // int      dest_heigjt : 회전할 비트맵 이미지의 높이 크기 == 회전할 비트맵 이미지가 출력될 높이 크기   
  13. // float    angle       : 회전할 각도.   
  14. // COLORREF bkColor     : 회전후 생긴 공백영역을 칠할 색상. 이미지 사각형을 회전하면, 공백영역이 생깁니다. (예)다이아몬드 형태로 회전된 사각형에서의 뒤부분 영역   
  15. //                        그 공백영역을 미리 채울 색상을 지정합니다.   
  16.   
  17. HBITMAP GetRotatedBitmap( HDC hdc, HBITMAP hBitmap, int source_x, int source_y,   
  18.                           int dest_width, int dest_height, float angle, COLORREF bkColor )   
  19. {     
  20.     HDC sourceDC        = CreateCompatibleDC(hdc);                                      // 회전할 비트맵 원본을 선택할 DC   
  21.     HDC destDC          = CreateCompatibleDC(hdc);                                      // 회전할 비트맵을 출력받을 DC   
  22.     HBITMAP hbmResult   = CreateCompatibleBitmap( hdc, dest_width, dest_height );       // 회전할 비트맵을 출력받을 메모리비트맵 핸들   
  23.   
  24.     HBITMAP hbmOldSource= (HBITMAP)SelectObject( sourceDC, hBitmap );                   // 회전할 비트맵 원본을 DC에 선택   
  25.     HBITMAP hbmOldDest  = (HBITMAP)SelectObject( destDC, hbmResult );                   // 회전할 비트맵을 출력받을 DC에, 회전할 비트맵을 출력받을 메모리비트맵 선택   
  26.   
  27.     HBRUSH hbrBack      = CreateSolidBrush( bkColor );                                  // 회전으로 인한, 공백영역을 칠할 브러시핸들 생성   
  28.     HBRUSH hbrOld       = (HBRUSH)SelectObject( destDC, hbrBack );                      // 브러시핸들 선택   
  29.     PatBlt( destDC, 0, 0, dest_width, dest_height, PATCOPY );                           // 선택된 브러시로, 회전할 비트맵을 출력받을 DC에, 미리 색상을 채워 지움   
  30.     DeleteObject( SelectObject( destDC, hbrOld ) );                                     // 브러시 해제   
  31.   
  32.     angle           = (float)( angle * PI / 180 );                                      // 회전할 각도(360분법)를, 라디안단위의 각도로 변경   
  33.     float cosine    = (float)cos( angle );                                              // 회전이동변환 행렬에 들어갈 cos세타 값을 구함          
  34.     float sine      = (float)sin( angle );                                              // 회전이동변환 행렬에 들어갈 sin세타 값을 구함   
  35.   
  36.     SetGraphicsMode(destDC, GM_ADVANCED);                                               // 윈도우 좌표계의 회전을 위하여, 그래픽모드를 확장모드로 변경합니다.(요구사항:윈98,NT이상)   
  37.   
  38.     // 회전이동변환 행렬을 정의.   
  39.     // (윈도우즈 API정복 개정판 2권 Page(1279) 참조.)   
  40.     // (게임 프로그래머를 위한 기초수학과 물리 Page(196) 참조.)   
  41.   
  42.     XFORM xform;                                                                        // 방정식을 표현하는 3행3열의 행렬 선언   
  43.     xform.eM11 = cosine;                                                                // 1행 1열 성분 설정 (회전성분)   
  44.     xform.eM12 = sine;                                                                  // 1행 2열 성분 설정 (회전성분)   
  45.     xform.eM21 = -sine;                                                                 // 2행 1열 성분 설정 (회전성분)   
  46.     xform.eM22 = cosine;                                                                // 2행 2열 성분 설정 (회전성분)   
  47.     xform.eDx = (FLOAT)dest_width / 2.0f;                                               // 3행 1열 성분 설정 (X축 이동 성분)   
  48.     xform.eDy = (FLOAT)dest_height / 2.0f;                                              // 3행 2열 성분 설정 (Y축 이동 성분)   
  49.   
  50.     // 설정한 행렬로, 인수DC의 윈도우즈 좌표계를 변환.   
  51.     // 인수DC는 출력대상으로 메모리비트맵을 가지므로,   
  52.     // 선택하고 있는 메모리비트맵의 좌표체계가 회전된다.   
  53.   
  54.     SetWorldTransform( destDC, &xform );   
  55.   
  56.     // 회전된 메모리DC에, 회전할 이미지를 출력   
  57.   
  58.     BitBlt(destDC, -(dest_width/2),-(dest_height/2), dest_width, dest_height, sourceDC, source_x, source_y, SRCCOPY );    
  59.   
  60.     // 사용된 자원 해제   
  61.   
  62.     SelectObject( sourceDC, hbmOldSource );    
  63.     SelectObject( destDC, hbmOldDest );    
  64.     DeleteObject(sourceDC);   
  65.     DeleteObject(destDC);   
  66.   
  67.     // 회전된 비트맵 핸들 리턴   
  68.   
  69.     return hbmResult;    
  70. }   
  71.   
  72. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////   
  73. // 인수 목록   
  74. // HDC      hdc         : 화면DC의 핸들. GetRotatedBitmap()함수의 인자로 전달하게 됩니다.   
  75. // HDC      hOffScreen  : 회전 이미지를 출력할, 오프스크린DC의 핸들.   
  76. // int      dest_x      : 오프스크린 상에서, 회전 이미지가 출력될 x좌표.   
  77. // int      dest_y      : 오프스크린 상에서, 회전 이미지가 출력될 y좌표.   
  78. // int      dest_width  : 회전할 비트맵 이미지의 폭   크기 == 회전할 비트맵 이미지가 출력될 폭 크기   
  79. // int      dest_heigjt : 회전할 비트맵 이미지의 높이 크기 == 회전할 비트맵 이미지가 출력될 높이 크기   
  80. // HBITMAP  hBit        : 회전 이미지 비트맵핸들   
  81. // int      source_x    : 회전 이미지 비트맵에서의, 출력할 사각영역의 좌상단x좌표.   
  82. // int      source_y    : 회전 이미지 비트맵에서의, 출력할 사각영역의 좌상단y좌표.   
  83. // DWORD    dFlag       : ROP모드를 나타내는 플래그 매크로   
  84. // float    angle       : 회전할 각도.   
  85. // COLORREF bkColor     : 회전후 생긴 공백영역을 칠할 색상. 이미지 사각형을 회전하면, 공백영역이 생깁니다. (예)다이아몬드 형태로 회전된 사각형에서의 뒤부분 영역   
  86. //   
  87. void RotateBlt( HDC hdc, HDC hOffScreen, int dest_x, int dest_y, int dest_width, int dest_height,   
  88.                 HBITMAP hBit, int source_x, int source_y, DWORD dFlag, float angle, COLORREF bkColor )   
  89. {   
  90.     static HDC hTempMemDC;              // 회전한 비트맵을 선택할 메모리DC   
  91.     HBITMAP hTempBitmap, hOldBitmap;    // 회전한 비트맵을 저장할, 비트맵 핸들   
  92.   
  93.     // 최초 한번만 비트맵DC를 생성합니다.   
  94.   
  95.     if( !hTempMemDC ) hTempMemDC = CreateCompatibleDC( hdc );   
  96.   
  97.     // 비트맵을 회전하는 함수를 호출하여, 리턴되는 회전된 비트맵 핸들을 저장   
  98.   
  99.     hTempBitmap = GetRotatedBitmap( hdc, hBit, source_x, source_y, dest_width, dest_height, angle, bkColor );   
  100.   
  101.     // 회전된 비트맵 핸들을 선택하고,   
  102.   
  103.     hOldBitmap = (HBITMAP)SelectObject( hTempMemDC, hTempBitmap );   
  104.   
  105.     // 오프스크린DC에, 회전된 비트맵 핸들을 선택한, 메모리DC의 이미지를 출력합니다.   
  106.     // 안의 주석을 해제하면, 출력좌표를 중심으로 하는 회전이미지가 됩니다.   
  107.   
  108.     BitBlt( hOffScreen, dest_x/* - dest_width/2*/, dest_y/* - dest_height/2*/, dest_width, dest_height,   
  109.             hTempMemDC, 0, 0, dFlag );   
  110.   
  111.     SelectObject( hTempMemDC, hOldBitmap );   
  112.     DeleteObject( hTempBitmap );   
  113. }   
  114.   
  115. HWND    hWndMain;                   // 윈도우 핸들   
  116. HDC     hdc;                        // 화면         DC 핸들   
  117. HDC     hOffScreenDC;               // 오프스크린 DC 핸들   
  118. HBITMAP hOffScreenBitmap;           // 오프스크린 DC 가 선택하는, 메모리 비트맵 핸들   
  119. HBITMAP hMemBitmap;                 // 이미지를 담을, 메모리 비트맵 핸들   
  120.   
  121. void OnTimer();                     // WM_TIMER메세지의, 핸들러 함수   
  122.   
  123. LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )   
  124. {   
  125.     switch( message )   
  126.     {   
  127.         case WM_CREATE:   
  128.             hWndMain = hWnd;   
  129.             // 화면DC, 오프스크린DC, 오프스크린의 메모리비트맵을 미리 생성합니다.   
  130.   
  131.             hdc = GetDC( hWnd );   
  132.             hOffScreenDC = CreateCompatibleDC( hdc );   
  133.             hOffScreenBitmap = CreateCompatibleBitmap( hdc, 800, 600 );   
  134.             SelectObject( hOffScreenDC, hOffScreenBitmap );   
  135.             PatBlt( hOffScreenDC, 0, 0, 800, 600, WHITENESS );   
  136.   
  137.             // 이미지를 비트맵에 로드합니다.   
  138.   
  139.             hMemBitmap = (HBITMAP)LoadImage( GetModuleHandle(NULL),   
  140.                                              TEXT("player_walk.bmp"),   
  141.                                              IMAGE_BITMAP,   
  142.                                              0,   
  143.                                              0,   
  144.                                              LR_DEFAULTSIZE | LR_LOADFROMFILE );   
  145.   
  146.             // 타이머 생성   
  147.   
  148.             SetTimer( hWnd, 1, 20, NULL );   
  149.             break;   
  150.   
  151.         case WM_TIMER:   
  152.             OnTimer();   
  153.             break;   
  154.   
  155.         case WM_DESTROY:   
  156.             // 사용된 메모리 비트맵과, 오프스크린 DC, 타이머를 해제합니다.   
  157.             DeleteObject( hMemBitmap );   
  158.             DeleteObject( hOffScreenBitmap );   
  159.             DeleteDC( hOffScreenDC );   
  160.             KillTimer( hWnd, 1 );   
  161.             PostQuitMessage(0);   
  162.             break;   
  163.     }   
  164.   
  165.     return DefWindowProc( hWnd, message, wParam, lParam );   
  166. }   
  167.   
  168. void OnTimer()   
  169. {   
  170.     // 비트맵을 회전시킬 각도(360분법) 갱신   
  171.   
  172.     static FLOAT angle  = 0.0f;   
  173.     static BOOL bRotate = FALSE;   
  174.   
  175.     if( GetKeyState( VK_LBUTTON ) & 0x8000 ) { bRotate = TRUE; }   
  176.   
  177.     if( bRotate )   
  178.     {   
  179.         angle += 5.0f;   
  180.         if( angle >= 360.0f )   
  181.         {   
  182.             bRotate = FALSE;   
  183.             angle = 0.0f;   
  184.         }   
  185.     }   
  186.   
  187.     // 오프스크린DC의 이미지를, 하얀색으로 채워, 이전 프레임에서의 이미지를 삭제합니다.   
  188.   
  189.     PatBlt( hOffScreenDC, 0, 0, 800, 600, WHITENESS );   
  190.   
  191.     // 오프스크린DC에, 이미지의 마스크를 출력합니다.   
  192.   
  193.     RECT Rt;   
  194.     GetClientRect( hWndMain, &Rt );   
  195.     RotateBlt( hdc, hOffScreenDC, Rt.right / 2, Rt.bottom / 2, 59, 59,   
  196.                hMemBitmap, 0, 0, SRCAND, angle, RGB( 255, 255, 255 ) );   
  197.   
  198.     // 오프스크린DC에, 이미지를 출력합니다.   
  199.   
  200.     RotateBlt( hdc, hOffScreenDC, Rt.right / 2, Rt.bottom / 2, 59, 59,   
  201.                hMemBitmap, 60, 0, SRCPAINT, angle, RGB( 0, 0, 0 ) );   
  202.   
  203.     // 화면DC에, 오프스크린의 이미지를 출력합니다.   
  204.   
  205.     BitBlt( hdc, 0, 0, 800, 600, hOffScreenDC, 0, 0, SRCCOPY );   
  206. }  

    출처 : http://mumbi.net/216
Comment 0 Trackback 0

Trackback : http://sepoc.tistory.com/trackback/47 관련글 쓰기

Top

[LINKUBE-SCRIPT] IWebBrowser2


IWebBrowser2 Interface

 

This interface enables applications to implement an instance of the WebBrowser control (Microsoft® ActiveX® control) or control an instance of the InternetExplorer application (OLE Automation). Note that not all of the methods listed below are supported by the WebBrowser control.

 

이 인터페이스는 어플리케이션에게 웹브라우저 컨트롤(MS ActiveX control)로 부터 인스턴스를 전달 하거나, 인터넷 익스플로어 어플리케이션(OLE Automation?)의 인스턴스를 조정 할 수 있도록 한다.

주. 아래의 리스트는 WebBrowser 컨트롤이 지원하는 메소드들 중 불필요한 메소드는 생략 하였다.

 

 

IWebBrowser2 Member

 

AddressBar  : Sets or retrieves whether the address bar of the object is visible or hidden.

                  : 툴바의 주소부분을 숨기거나 표시할 때 사용하는 값을 읽거나 지정할수 있다.

Application  : Retrieves the automation object for an application that is hosting the WebBrowser Control.

                 : 웹브라우저 컨트롤상의 어플리케이션내의 자동화객체(?)를 읽을수 있다.

Busy  : Retrieves a BOOL value indicating whether the object is engaged in a navigation or downloading operation.

         : 다운로드 작업 중이거나 페이지가 로딩되고 있는지에 대한 여부를 이진 논리값으로 얻을 수 있다.

ClientToWindow  : Converts the client coordinates of a point to window coordinates.

                        : 클라이언트의 좌표를 윈도우 좌표 포인트로 전환시킨다. (왜 필요해 -_-?)

Container  : Retrieves an object reference to a container.

               : 포함된 객체에 대한 참조객체의 값을 얻는다. (??)

Document  : Retrieves the automation object of the active document, if any.

                : 자동화 객체의 활성화중인 문서의 값을 읽는다. if any. (??)

ExecWB  : Executes a command on an OLE object and returns the status of the command execution using the IOleCommandTarget interface.

             : IOleCommandTarget 인터페이스를 이용해서 OLE 객체에 명령을 실행하고, 실행에 대한 상태값을 받는다.

FullName  : Retrieves the fully qualified path of the Microsoft Internet Explorer executable file.

               : 인터넷 익스플로어에서 실행할 수 있는 파일의 경로를 포함한 전체 경로을 받는다.

FullScreen  : Sets or retrieves a VARIANT_BOOL value that indicates whether Internet Explorer is in full-screen or normal window mode.

                : 익스플로어가 풀스크린인지 일반 윈도우 모드인지에 대한 값을 VARIANT_BOOL 형식으로 받거나 설정이 가능하다.

GetProperty  : Retrieves the value of a property associated with the given object.

                  : 주어진 객체에 대한 주어진(조합된?) 프로퍼티 값을 얻는다.

GoBack  : Navigates backward one item in the history list.

             : 히스토리 리스트에서 이전페이지로 돌아간다.

GoFoword  : Navigates forward one item in the history list.

                 : 히스토리 리스트에서 이 후 페이지로 이동한다.

GoHome  : Navigates to the current home or start page.

              : 시작 페이지로 이동한다.

GoSearch  : Navigates to the current search page.

                : 설정된 검색 페이지로 이동한다.

Height  : Sets or retrieves the height of the Internet Explorer main window.

          : 익스플로어 메인 윈도우의 높이에 대한 값을 얻거나 설정 한다.

HWND  : Retrieves the handle of the Internet Explorer main window.

          : 익스플로어 메인 윈도우의 메세지 핸들을 얻는다.

Left  : Sets or retrieves the screen coordinate of the left edge of the main window of the object.

       : 객체의 메인 윈도우의 왼쪽 끝 좌표에 대한 값을 얻거나 설정한다.

LocationName  : Retrieves the name of the resource that Internet Explorer is currently displaying.

                      : 익스플로어에 표시되고 있는 자원에 대한 이름 값을 얻는다.

LocationURL  : Retrieves the URL of the resource that Internet Explorer is currently displaying.

                    : 익스플로어에 표시되고 있는 자원에 대한 URL 값을 얻는다.

ManuBar  : Sets or retrieves a VARIANT_BOOL value that indicates whether the Internet Explorer menu bar is visible.

              : 익스플로어의 메뉴바가 보이고 있는지에 대한 값을 VARIANT_BOOL 형태로 얻거나 설정이 가능하다.

Name  : Retrieves the name of the object that contains the WebBrowser Control used by Internet Explorer.

         : 익스플로어에서 사용하고 있는 웹브라우저 컨트롤에 대한 객체 이름을 얻는다(?)

Navigate  : Navigates to a resource identified by a URL or to the file identified by a full path.

              : 자원의 URL이나 파일의 경로를 통해서 페이지를 연다. (해석이...)

Navigate2  : Navigates the browser to a location that might not be able to be expressed as a URL, such as a pointer to an item identifier list (PIDL) for an entity in the Microsoft Windows® shell namespace.

Comment 0 Trackback 0

Trackback : http://sepoc.tistory.com/trackback/35 관련글 쓰기

Top

[이것이 리얼 윈도우] wii리모컨으로 구현한 시선추적 시스템





이걸 우리 프로그램에 적용하면..
농담
UI는 완벽하게 해결인데..
농담임


Johnny Chung Lee라는 사람이 Wiimote 하나로 구현한 headtracking 시스템.
Comment 0 Trackback 0

Trackback : http://sepoc.tistory.com/trackback/31 관련글 쓰기

Top

API 팁들 모음

API 팁들 모음

Visual C++의 유용한 단축키>

* Ctrl+F3 : 현재 커서가 있는 위치의 단어가 나오는 다음 위치를 찾아줍니다. Ctrl+Shift+F3을 누르면 이전 걸 찾아주죠.

* Ctrl+H : replace입니다. 특히 일정부분안의 변수 이름을 변경하거나 할 때 범위를 선택한 다음에 Ctrl+H를 누르면 편하죠.

* Ctrl+], Ctrl+E : 괄호 짝을 맞춰줍니다. {위에서 누르면 짝이 맞는 }를 찾아주지요.

* Ctrl+L : 한줄을 잘라냅니다. -> 클립보드로

* Ctrl+Shift+L : 한줄을 지웁니다.

* Ctrl+J, K : #ifdef ... #endif 쌍을 찾는데 사용합니다.

* 그외 Ctrl을 누르고 커서나 Delete, Backspace를 누르면 단어 단위로 동작을 하게 됩니다.

* Alt+F8 : 인덴트 정리. 일정 범위를 선택하고 누르면 라인 앞부분의 공백을 자동으로 조정해줍니다.

* CTRL+SHIFT+T : 커서 위치의 단어와 앞 단어가 서로 교체 됩니다.

* ALT+SHIFT+T : 커서 위치의 한줄과 윗줄이 서로 교환됩니다.

* Shift + F9 : 디버그 모드에서 추가하고픈 변수나 등등 앞에 커서를 위치 시킨후 Shift+F9를

누르면 Watch Window에 자동으로 추가.

* Ctrl + Alt + T , Ctrl + Spacebar : 멤버목록 팝업창이 나타납니다 (참고로 대소문에 관계없습니다.)

* Ctrl + Shift + U : 소문자를 대문자로 바꾸고 싶을때 블럭 지정을 한다음 이 키를 누르면 소문자가 대문자로 둔갑.

* Ctrl + U : 대문자를 소문자로 변경

* Ctrl + Shift + 8 : Tab은 ^모양으로 공백문자는 .로 변경, 다시 누르면 설정이 해제



<ALT+F4로 종료안되게 하려면>

BOOL MyApp::PreTranslateMessage(MSG* pMsg)
{
        if(pMsg->message == WM_SYSKEYDOWN &&
                pMsg->wParam == VK_F4) {
                      return TRUE;
        }
}

이 함수를 오버라이드 하여서 집어넣으면 됩니다.  



<제일 짧은, 파일 크기 알아내는 함수>

일단 제가 본 방법들을 열거해 보겠습니다.

      1] 파일을 열고, 파일 끝으로 위치를 옮겨서 그 위치값을 읽는다.

      2] 파일을 fopen()이 아닌 open()으로 열어서 핸들을 얻은 다음 그것을 이용해서 filelength()함수로 파일 크기를 구한다.



간단하니 결론만 말씀드리죠. 저는 다음과 같이 파일 크기를 구합니다.

      fileSize = filelength( fileno(fp) );

fp는 FILE *fp; 로 정의된 파일 포인터입니다.

물론 fopen()으로 파일을 연 상태에만 가능합니다.

그러나 파일 크기를 구한다는 것이 DIR프로그램이 아닌 이상 파일을 열고나서 구하는 거 아니겠습니까?



<클래스 이름 등록방법>

PreCreateWindow(CREATESTRUCT& cs)에서 cs.lpszClass를 변경해주면 될 것 같은데 잘되지 않는 경우가 있습니다. 이부분에서 사용자들이 헤매는 경우가 많이 있죠.

다음의 코드를 활용하시면 잘되실 겁니다.



BOOL CTestDlg::PreCreateWindow(CREATESTRUCT& cs)
{
     if(!CWnd::PreCreateWindow(cs))
          return FALSE;

     HINSTANCE hInst=AfxGetInstanceHandle();
     WNDCLASS wc;

     ::GetClassInfo(hInst, cs.lpszClass, &wc);
     wc.lpszClassName=cs.lpszClass="MyClass";

     return AfxRegisterClass(&wc);
}



<외국 리소스를 한글 리소스로 수정하기>

1. 간단하게 고치기

영국인가 에서 만든 소스를 분석하다가 리소스를 볼려고 누르니 언어가 다르다고 안나오더군요 계속 고민하다가 이럴 때는 rc화일에서

원래 코드

//*****************************************************
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
//*****************************************************



한국말로 수정한뒤 코드

//******************************************************
#if !defined(AFX_RESOURCE_DLL)||defined(AFX_TARG_KOR)
#ifdef _WIN32
LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT
#pragma code_page(949)
#endif//_WIN32
//******************************************************



이렇게 수정해주니 코드가 나오더군요.

물론 다아시겠지만 열기에서 rc화일을 text로 열어서 수정해주셔야겠지요



2. 근본적 해결방법

다 아시겠지만 VC++은 다국어 리소스를 지원합니다.

외국에서 만든 샘플 예제를 Down받아서 리소스를 오픈할때 현재 시스템의 코드 페이지와 다르면 오픈되지를 않습니다.

지원하지 않는 코드 페이지 때문에 리소스가 제대로 오픈되지 않는다면 해당하는 코드 페이지의 .nls(National Language Support)파일을 시스템에 복사해 넣어주면 됩니다.

해당 nls파일은 Win95/98 CD에 있고 이파일(예:cp_1252.nls)을 windows system 폴더안에 복사한 후 레지스트리(\HKEY_LOCAL_MACHINE\System\CurrentControlSet\control\Nls\Codepage)에 수동으로 등록시켜 주면 됩니다.



<F10 키를 처리하기>

도스시절 프로그램에서 F10 키는 주로 풀다운 메뉴를 띄우는데 사용됩니다.

그래서 우리는 F10 으로 메뉴를 뛰우는데 익숙하죠. 윈도에서도 마찬가지로 F10 키가 메뉴를 활성화시키는데 사용되죠. F10 키가 메뉴를 활성화 하는 것을 막고 나의 고유 기능을 실행하게 할려면 어떻게 해야 하죠?

몇가지 방법이 있는데...

1.- SetWindowsHookEx() 의 사용

키보드의 행동을 바꾸기 위해서 SetWindowsHookEx 함수를 사용하는 것입니다.우선 키보드 훅(Hook)을 작성하고 쓰레드 전반에 이 훅을 설치하는 것이죠.코딩이 좀 까다롭지만..오버헤드가 별루 없기 때문에 ..가장 좋은 제안이 될것입니다.

2.- PreProcessMessage() 와 WM_SYSKEYDOWN 테스트

메시지 선처리기인 PreProcessMessage 에서 WM_SYSKEYDOWN 메시지가 발생했을때 F10 키인지 확인하는 것입니다.그러나 매번 조사해야 하기 때문에 (모든 키에 대해서..) 많은 오버헤드를 발생시켜 속도저하를 가져옵니다.

3.- F10 키에 대한 억셀레이터 테이블 작성

추천할만한 다른 좋은 방법입니다. 그러나 잘 안먹힐때가 있어서.

4.- OnSysKeyDown() 핸들러에서 F10 테스트

문서화되어 있는 방법이죠...그런데 ...이해할수 없는건..

MFC 에서는 F10 키에 대한 SysKeyDown 메시지를 SDI View 에 보내지 않습니다. 문제의 소지가 되죠.



<ESC키로부터 Dialog 사라짐을 방지>

ESC키로부터 Dialog 사라짐을 방지하려면



// 멤버 변수
        BOOL m_bClose

// 생성자
        m_bClose = FALSE;

// OnClose
void CKeyDlg::OnClose()
{
        m_bClose = TRUE;
        CDialog::OnClose();
}

// WindowProc
LRESULT CKeyDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
        if( message == WM_COMMAND && wParam == WM_DESTROY )
        {
                if( m_bClose == FALSE )
                        return NULL;
                // esc키로 부터 다이얼로그 사라짐을 방지
                // 요길 FALSE(NULL)로 막아주면
                // (정상적으로는 아래 return 값이 1로 됨)
                // 다음에 message WM_DESTROY, WM_NCDESTROY가
                // 날아오지 않아 종료 되지 않음
        }
        return CDialog::WindowProc(message, wParam, lParam);
}


/// 참고
// dialog에서 esc 또는 close 버튼은  message - 111, wParam - 2 가 날아옴
// return 값이 TRUE 이면
// message - 2에 이어 message -82가 날아옴


//#define WM_COMMAND                      0x0111
//#define WM_DESTROY                      0x0002
//#define WM_NCDESTROY                    0x0082
//#define WM_CLOSE                        0x0010

/* Enter 키 */

버튼 중에 Property에 Default라고 체크가 된 것이 있을 것입니다.

버튼중 하나만이 이 속성을 가질 수 있는데 Enter키를 치면 이 버튼이 실행됩니다.

Default로 IDOK버튼이 먹게 되지요. 해서 다른 버튼에 이속성을 주거나 IDOK버튼의  함수를 고치세요.



<fscanf()에서 쓸데 없는 값 읽지않고 버리기>

화일명: aaa.dat
자료: 1 2.0 3

이럴경우 자료를 fscanf()로 읽어 들일 때 불필요한 자료가 있을 수 있습니다. 만약 위의 데이터를 읽어 들인다면 -> 실제로 2.0은 필요 없는 자료라 가정하고

int a, b;
float dummy;
FILE* fp;

if((fp = fopen("aaa.txt", "r"))== NULL)
   return;

fscanf("%d %f %d", &a, &dummy, &b);
fclose(fp);

일반적으로 필요없는 2.0도 dummy라고 읽어 들인다음 버립니다.

이런 쓸데가 없는 데이터를 읽어 들이면 시간도 낭비고... 에구 코드도 복잡하고....

이럴 경우 *를 사용하시면 아주 좋죠... ^^;

fscanf("%d %*f %d", &a, &b);

요렇게 바꾸면 실수형 자료가 나오면 그냥 넘어 가요...

각각의 데이터 자료형만 맞추어 주면 그냥 안읽고 넘어간 다음에 그 다음 데이터를 읽지요

자신이 만든 데이터라면 이런 경우가 없겠지만 남이 만든 데이터를 읽어 올 경우에

자기에게 불필요한 데이터가 생길 경우 일일이 다 읽어서 버린다면 넘 짜증 나겠지요 ^^;



<Toggle 기능 구현하기>

버튼을 누를 경우 서로 토글되는 기능을 구현 하겠습니다.

static int rwflg = 1;
rwflg = !rwflg;//가장 중요
if(rwflg) {
      // 버튼을 누를 경우 두번째 실행.
} else {
      //버튼을 누를 경우 처음 실행
}



<한글 윈도우에서 일본어 프로그램 빌드하기>

일단. 리소스는 당연히 일본어 코드로 변환되어 있어야 합니다. 한글 윈도우에서 보면 코드가 깨져 보이겠지요? 코드 변환 방법은 Microsoft Word 같은 걸 이용하셔도 되고, 아니면 프로그램을 만드셔도 되구요.. 가능하면 리소스 작업은 일본어 윈도우에서 하시기를 권합니다. Copy&Paste 로 했는데도, 일부코드가 깨어지는 문제가 있더라구요.. 정확히 이유는 모르겠지만, 리소스의 Text 를 붙여넣는 작업은 가능한한 일본어 윈도우에서 하시기를 권합니다. 그리고 빌드하실 프로젝트의 리소스 파일(*.rc 파일) 에는 한국어가 있으면 절대로 안됩니다!! 테스트를 위해서 몇개의 다이얼로그만 일본어로 바꿨는데 빌드가 안되더군요.. 반드시 전체 리소스 파일에는 영어 아니면 일본어 코드만 존재 해야 합니다.

그리고 Resource file (rc 파일들)의 내용을 다음과 같이 바꾸시면 됩니다. 모든 부분을 바꾸어야 하는지는 확실치 않지만, 일단 이렇게 바꾸면 빌드랑 실행에 문제는 없습니다..

1. #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_KOR) 를

    #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN) 으로...

2. LANGUAGE 18, 1 를

    LANGUAGE 17, 1 로...

3. #pragma code_page(949) 를

    #pragma code_page(932) 로...

4. l.kor\\afxres.rc 를

    l.jpn\\afxres.rc 로..

이상입니다.. ^^.. 도움이 됐을까요?? 그리고 주의하실 점은 Font 입니다.. 일본의 폰트에 맞추어 크기랑 이름을 정해줘야만 하지요..



<#과 ##>

'##'에 대안 질문이 나온 김에 '#'과 '##' 대해 이야기를 한번 해볼까 합니다.

먼저 #부터 시작하겠습니다.

#은 C/C++에서 많이 나오는 기호죠. #include 랄지, #define 이랄지. 그런데, #이 다른 용도로 쓰이는 경우가 있습니다.

다음과 같은 코드가 있습니다.

#include <stdio.h>
#define STRING(a) printf(a)

void main(){
    STRING(trowind);
}

매크로를 아시는 분이라면 위에 코드가 어떻게 변환되는지 아실 겁니다. STRING(trowind) 부분이 printf(trowind)로 바뀌겠죠. (이 변환은 preprocessor에서 담당합니다. 자세한 내용은 'Preprocessor' 또는 '전처리기'에대한 자료를 참고하세요.)

이건 명백히 컴파일 에러입니다. trowind라는 변수가 없으니까요.

그럼 이제 STRING() 매크로 함수를 다음과 같이 바꿔보겠습니다.

#define STRING(a) printf(#a)

바꾼거라고는 'a' 앞에 #를 붙인 것 밖에 없습니다. 그러면 위의 STRING(trowind) 는 다음과 같이 바뀝니다.

printf("trowind")

즉 #의 용도는 매크로에서 치환되는 문자열에 큰따옴표를 붙여주는 것입니다. 이걸 잘 이용하면 다음과 같은 기능을 구현할 수 있죠.

#include <stdio.h>
#include <stdlib.h>

// MFC에도 ASSERT란 매크로가 있기 때문에 MY_ASSERT로 합니다.
#defien MY_ASSERT(a) if ( !a ) { printf("Error : "); printf(#a); }

void main() {
    int a = 0;
    int b = 1;
    MY_ASSERT(a > b)
}

(결과는 직접 확인해 보시기 바랍니다.)



##은 #과는 다르게 작동합니다. ##은 주어진 문자열을 그대로 바꿔줍니다. 예를 들어보죠.

다음과 갈은 매크로가 있습니다.

#define RUNTIME_CLASS(class_name) class##class_name;

그럼 다음과 갈이 됩니다.

RUNTIME_CLASS(CMyDocument) -> classCMyDocument

##은 그 사용 예를 찾기가 쉽진 않죠. 하지만, MFC에서는 이 ##을 기가막히게 잘 사용합니다.  MFC로 애플리케이션을 만들 때 기본적으로 만들어지는 클래스 중에 View나 Document 클래스에 보면 DECLARE_DYNCREATE, IMPLEMENT_CYNCREATE 매크로가 있습니다. 이 매크로를 한번 분석해 보세요.



<드라이브 포맷하기>

MSDN에는 설명이 하나도 없네요..



DWORD WINAPI SHFormatDrive(HWND hwnd, UINT drive, UINT fmtID, UINT option)



이런 형식입니다..드라이브는 ID가

0=A, 1=B,2=C....

fmtID는 -1이구여..

option은

0 - 빠른포맷

1 - 전체포맷

2 - 시스템 디스크 작성



<에디트박스에서 커서를 임의의 위치에>

음.. 에디트 박스에서 커서를 뒤쪽이나.. 임의의 위치에 놓을 수 있는 방법을 물어 보시는 분께 도움될 자료입니다.

1. 커서를 맨 끝에

SetSel(-1, -1);

2. 커서를 임의의 위치에

SetSel(n, n);

======================================
1. 응용할 멤버 함수
======================================

에디트 박스의 멤버 함수중에서 커서를 임의의 위치에 놓을 처리를 하는 함수는 SetSel( ... ) 과 ReplaceSel( ... ) 입니다.

두 함수는 많이 사용되기 때문에 아시고 계시리라 믿~~습니다.

  ex) 에디트 박스의 멤버 변수를 다음과 같이 정의된 상태에서 예를 들어 가면서 설명을 드립니다.

      CEdit   변수 m_editMyBox;
      CString 변수 m_strMyBox;

======================================
2. 커서를 맨 뒤쪽에 놓기
======================================

  커서를 맨 뒤쪽에 놓는 방법은 의외로 간단 합니다.

   UpdateData( TRUE );

  //--> 전체를 선택
  m_editMyBox.SetSel( 0, -1 );        

  //--> 현재의 데이터로 다시 치환
  m_editMyBox.ReplaceSel( m_strMyBox );

  //--> 포커스를 에디트 박스로 설정
  m_editMyBox.SetFocus();

이렇게 처리하시면 커서가 데이터의 제일 끝에 놓일 겁니다.

======================================
3. 커서를 임의의 자리에 놓기
======================================

방법은 마찬가지로..SetSel(..) 과 ReplaceSel(...)을 이용하는 것인데요..

어떤 형태로 응용할 수 있냐 하면..

  SetSel( 시작 위치, 끝 위치, ..?? 안살펴 봤음..세번째 인자)에서 보면, 시작 위치를 처음(0)으로 하고 끝 위치를 커서가 놓이고자 하는 위치로 지정한 후에, 현재의 데이터를 처음부터 커서가 놓이고자 하는 위치까지 다른 버퍼에 복사한 후에, ReplaceSel로 복사 합니다.

소스 코드를 보시면 더 쉬우실 겁니다.

UpdateData( TRUE );

//--> 커서가 놓일 위치까지 복사할 임시 버퍼(크기는??)
char cDataBuf[100];

//--> 쓰레기 값을 방지하기 위해.. 초기화
for( int i=0; i<100; i++ )    cDataBuf[i] = NULL;

//--- 6번째에 커서를 위치하고 싶을 경우...
for( i=0; i<6; i++ )
      cDataBuf[i] = m_strMyBox[i];

//****보충 설명.. CString 형의 데이터 같은 경우에서****

데이터를 원할때는 버퍼 형태로 사용을 하셔도 됩니다.

음.. 무슨 말이냐 하면.. 제가 CString 형으로 선언된 멤버 변수 m_strMyBox의 데이터를 임시 버퍼에 복사하는 과정에서 m_strMyBox[i]라고 사용을 했는데..

m_strMyBox는 에디트 박스의 멤버 변수이거든요.

위와 같은 방법을 복사를 하셔도 되고.. 다른 방법도 있겠죠..

//--> 원하는 위치만큼 지정
     m_editTest.SetSel( 0, 6 );

//--> 바꾸면 되겠죠.. 복사된 내용으로..
     m_editTest.ReplaceSel( cDataBuf );

//--> 포커스를 놓으면.. 끝..
     m_editTest.SetFocus();



이렇게 처리하면.. 에디트 박스에서 제일 끝이나 임의의 자리에 커서를 놓을 수 있군요..



<릴리즈 버젼 실행시 런타임 에러 찾아내기>

릴리즈 버젼 실행시 에러가 났을 경우..참 곤란했죠.

물론 고수님들께서야 이미 알고계시겠지만..

나름대로 엄청 가슴이 아팠습니다. 디버그모드는 괜찮은데..릴리즈는 에러를 때리구..어디서 나는지조차 모르겠구...그때 쓸만한 잼있는 방법입니다.(물론 모르는 분에 한해서..^^)



Step 1.

프로젝트 세팅 들어가면..

Link라는 탭 선택해서..보면

Generate Mapfile이라구 있을꺼랍니다.

고걸 선택해서 샥 돌려보면..map파일이 release디렉토리에 생기죠.



Step 2.

그리구 나선..에러를 만들어 돌려보고, 어느 주소에서 에러가 났는지 캡춰

그리구서 map파일에 있는 주소랑 매치해 보는겁니다.

그럼 어느 함수에서 에러가 났는지 알 수 있죠~



<모든 Top Level Windows 에게 메세지 보내기>

SendMessage 아시져? 거기에서 HWND 인자에 HWND_BROADCAST을 넣으면,모든 윈도우에게 메세지가 간답니다..



<일반적인 윈도 소멸 순서>

MFC framework에서, 사용자가 frame 윈도를 닫게되면, 윈도는 기본적으로 OnClose 핸들을 call 한다. OnClose 내부에서는 DestroyWindow를 호출한다. 가장 마지막으로 호출되는 함수는 OnNcDestroy이다. 이 함수는 약간의 정리를 하는 함수로 윈도를 정리하기 위하여 기본적으로 불려지는 함수 이다. OnNcDestroy함수 내부에서는 PostNcDestroy함수를 호출한다.

afx_msg OnClose( )

Framework은 CWnd나 application을 종료 시키기 위해서 이 함수를 마치 시그날처럼 호출한다. 내부의 기본적인 구현은 DestroyWindow를 호출한다.

virtual BOOL DestroyWindow( )

Destroy Window 함수는

  1)  CWnd내부에 있는 윈도를 destroy 한다.

  2)  또한 윈도를 해제하고 입력 포커스를 제거하기 위한 적절한 message를 윈도에게 보낸다.

  3)  윈도의 메뉴 제거 

  4)  application queue를 비운다.

  5)  timer를 제거

  6)  clipboard의 소유주 제거

  7)  Clipboard-viewer chain을 끊는다. ( CWnd가 viewer chain의 맨 위에 있을 경우 )

  8)  WM_DESTROY( OnDestroy )와 WM_NCDESTROY( OnNcDestroy ) 메시지를 윈도에게 보낸다.

하지만 아직 CWnd 객체는 destroy하지 않는다.



이 함수를 오버라이드 하더라도 이 함수를 호출하지 않아도 된다. ( 왜냐면 시스템이 알아서 호출을 해주니까..) 뭐 굳이 하고 싶다면 해도 된다. 만약 내부에 자식 윈도가 있더라도 걱정하지 말자 자식들을 먼저 destroy한 다음에 자신이 죽으니까....



afx_msg void OnDestroy()

Framework이 CWnd에게 현재 CWnd가 소멸되고 있는 중이라고 알려 주기위하여 호출 한다. OnDestroy함수는 CWnd 함수가 화면에서 사라진 다음에 호출된다.

OnDestroy is called first for the CWnd being destroyed, then for the child windows of CWnd as they are destroyed. It can be assumed that all child windows still exist while OnDestroy runs.



afx_msg void OnNcDestroy()

Client가 아닌  영역이 destroy될 때 Frame work에 의하여 불려지는 함수이다. 윈도가 소멸될때 마지막으로 불려지는 함수이다. 기본적으로 약간의 정리를 한후, PostNcDestroy 함수를 호출한다. 대게는 이 함수를 오버라이드 하지 않지만 만약 하게되면 내부에서 상위 클래스의 OnNcDestroy를 호출해야만 한다. 그렇지 않으며녀 내부적으로 윈도를 위해 할당된 메모리가 free되지 못한다.



virtual void PostNcDestroy()

윈도가 소멸된 후 OnNcDestroy함수에 의하여 불려지는 기본함수이다. 사용자들이 상속받아 만든 클래스의 정리를 위한 코드를 삽입하면 된다. ( ex. delete this; )

위의 함수를 그냥 대충 보지 않고 세심히 본 사람이라면 이제 자신이 삽입하기를 원하는 코드를 어느부분에 삽입을 해야되는지 알 수 있을 것이다. 그럼 아래의 예를 통하여 알아보자.

먼저 View class에서는 3가지 소멸 핸들러를 제공한다. 다음을 보자.

BOOL CAniView::DestroyWindow()
{
         // TODO: Add your specialized code here and/or call the base class

         return CView::DestroyWindow();
}

void CAniView::OnDestroy()
{
        CView::OnDestroy();

        // TODO: Add your message handler code here
}

void CAniView::PostNcDestroy()
{
        // TODO: Add your specialized code here and/or call the base class

        CView::PostNcDestroy();
}

위에 나열 된 순서가 바로 view가 닫힐 때 불려지는 순서이다.   우리가 유심히 살펴 보아야할 부분은 TODO의 위치이다. 과연 어떤 이유에서 각각의 TODO의 위치가 결정 되는가?

만약  윈도가 없어지기 전에 작업을 해야할 일이 있다면   4번 중에 코드를 삽입하자. 또한 윈도가 사라진 다음에 작업을 해야 한다면 22번 줄에 삽입을 한다. delete this 함수를 사용한다면 25번째 줄에 삽입하자.

view에서는 제공되지 않지만  OnClose 함수도 TODO의 위치를 잠시 보자.

void CAboutDlg::OnClose()
{
      // TODO: Add your message handler code here and/or call default

      CDialog::OnClose();
}



<프로파일링[profiling]>

끝날때까지 어느 부분에서 어느 정도의 시간이 걸렸는지를 알 수가 있습니다.. 기타.. 다른 기능도 많이 있구요.. 

여러기능중에 function timing만 써봤거든요..

output 창에 나온 결과를 간단히 써보면..



program Statistics
------------------
    Command line at 2001 Jan 15
08:51: "D:\myProg\TestApp\PropertyTest\Debug\PropertyTest"
    Total time: 2848.924 millisecond
    Time outside of functions: 11.820 millisecond
    Call depth: 15
    Total functions: 141
    Total hits: 1868
    Function coverage: 51.8%
    Overhead Calculated 6
    Overhead Average 6

Module Statistics for propertytest.exe
--------------------------------------
    Time in module: 2837.104 millisecond
    Percent of time in module: 100.0%
    Functions in module: 141
    Hits in module: 1868
    Module function coverage: 51.8%

        Func          Func+Child           Hit
        Time   %         Time      %      Count  Function
---------------------------------------------------------
    2599.647  91.6     2716.741  95.8       44 CWinThread::PumpMessage(void) (mfc42d.dll)
     130.907   4.6      131.192   4.6      207 CWnd::DefWindowProcA(unsigned int,unsigned int,long) (mfc42d.dll)
      58.981   2.1     2835.973 100.0        1 CDialog::DoModal(void) (mfc42d.dll)



어느 함수가 시간이 젤 많이 걸린지 나오죠.. ^^;;

프로그램짜다가 나중에 한번 돌려보면..

어느 부분에서 퍼포먼스가 떨어지는지 확인할 수 있겠죠..

잡설은 고만하고..



Project 메뉴 Setting에서 Link 탭을 선택하면..

Enable Profiling 에 체크하시고..

Rebuild All 하신 후에..

Build메뉴 젤 아래에 Profile해주시면..

선택창이 뜨는데.. 선택하시고

프로그램 실행한후에.. 종료하면 output창에 결과가 나옵니다..



Windows 2000에서 profile 메뉴가 활성화되지 안된다는 분이 계시는데 해결 방법은 다음과 같습니다.

Visual Studio가 설치될 때 Profile과 관련된 레지스트리 정보를 HKEY_CURRENT_USER 아래에 써넣습니다. 그래서 Visual Studio를 설치할 때 사용했던 계정으로 로그인하지 않으면 profile이 활성화되지 않습니다.

이를 해결하려면 VC를 설치할 때 접속했던 계정으로 로그인을 하던가, 아니면 레지스트리에 값을 써넣어주면 됩니다. text editor를 이용하여 a.reg라는 파일을 만들고 다음의 내용을 넣어줍니다.

a.reg의 내용

REGEDIT4
[HKEY_LOCAL_MACHINE\Software\Microsoft\DevStudio\6.0\General]
"ProfilerInstalled"=dword:1


이 파일을 더블클릭하면 레지스트리에 값이 써넣어지고 VC에 profile 메뉴가 활성화됩니다.

이 정보는 MSDN에서 Q224382로 찾아보시면 됩니다.



<해상도 변경하기>

말 그대로 프로그래밍 상에서 현재의 해상도를 원하는데로 변경할 수 있습니다.

전역함수로 ChangeDisplaySettings 라는 함수가 있더군요.

암데서나 불러 쓸수 있죠. 

이전 해상도를 보관했다가 다시 복귀할 수 있도록 해보겠습니다.



현재의 해상도를 얻어오는 함수는 GetSystemMetrics 입니다.

먼저 현재의 해상도를 저장할 변수를 선언합니다.

class CMainFrame : public CMDIFrameWnd
{
      /// 생략
      // Attributes
 
public:
      int screenY;
      int screenX;
      /// 생략
}



초기화는 요렇게..

// 현재 해상도 보관
screenX = GetSystemMetrics(SM_CXSCREEN) ;
screenY = GetSystemMetrics(SM_CYSCREEN) ;

인자로 받은 해상도로 변경하는 함수를 만듭니다.

void CMainFrame::ChangeDisplay(int Width, int Height)
{
    DEVMODE mode ;
    mode.dmBitsPerPel = 16;   // 16비트 칼라로 변경
    mode.dmPelsWidth  = Width;
    mode.dmPelsHeight = Height;
    mode.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
    ChangeDisplaySettings(&mode, CDS_FULLSCREEN );
    ShowWindow( SW_SHOWMAXIMIZED );
}

전 16비트 칼라로만 변경하도록 했는데, 저것두 인자로 받아서 처리하면 원하는 칼라로 바꿀수 있겠죠??? 그리구 원하는 곳에서 함수를 호출~~~

    // 1024 x 768 로 변경   
    ((CMainFrame*)AfxGetMainWnd())->ChangeDisplay(1024, 768) ;    

프로그램이 종료할때 이전 해상도로 복귀하도록 해야 겠죠? 이건 DestroyWindow() 에서 처리하면 됩니다.

BOOL CMainFrame::DestroyWindow()
{
    if(screenX != GetSystemMetrics(SM_CXSCREEN) ||
        screenY != GetSystemMetrics(SM_CYSCREEN))
        ChangeDisplay(screenX, screenY) ;
    return CFrameWnd::DestroyWindow();
}

이전 해상도를 저장해뒀으니까 그걸로 다시 복귀한거죠.

암튼, 위에서처럼 작업하면 원하는 해상도로 변경시켜서 작업할 수 있죠.



참, 도움말을 뒤져보니깐 윈도우 메시지중에 WM_DISPLAYCHANGE 라는게 있더군요.

근데 이 메시지는 클래스위저드에 들어있질 않네요.

99999999WM_DISPLAYCHANGE 메세지는 직접 호출할 수는 없을 겁니다.

다만 OS가 화면 해상도가 변경되었을 때 모든 Window에게로

보내주는 Message일 겁니다.



해상도 복원시에 변수로 해상도를 가지고 있다가 복원할 필요 없이 그냥

    ChangeDisplaySettings(NULL, 0);

이라고만 하면 화면 복원 됩니다. 이 함수는 해상도 변경만 하지 디스플레이

등록정보 자체를 바꾸진 않기 때문에 위 방식대로 함수를 호출하면 디스플레이

등록정보에 있는 해상도로 그대로 바꿔주기 때문에 더 안정적입니다.



원하는 해상도를 모니터가 받아줄수 있는지 테스트 하시고 바꿔야죠.

그 부분이 빠졌군요.

EnumDisplaySettings를 이용하시면 됩니다.



< 화면 지우기>

1) OnDraw 와 InvalidateRect 이용

VC++ 에는 Basic의 CLS 명령과 같은 간단히 화면을 지우는 명령이 없습니다. 이때문에 다음과 간은 방법을 사용합니다. 예를 들면

CDC::Rectangle(x1,y1,x2,y2);

으로 사각형을 그린후 안을 배경색으로 모두 채우면 지운 것과 같은 효과를 내게 됩니다. windows는 외관상 화면에 문자출력이 되어 있어도 내부적으로는 모두 이미지를 그리기 때문에 이 명령으로 화면을 지울수가 있습니다.

OnDraw 함수와 InvalidateRect 함수를 사용하는 것으로도 간단하게 화면을 지울수 있습니다.

1 OnDraw 함수에 if문을 나누어 놓아서 아무 것도 표시하지 않는 기능을 넣습니다.

2 CWnd::GetclientRect 함수에서 클라이언트 영역 크기를 알아 낸다.

3 그 크기를 파라미터로 하여 InvalidateRect 함수를 실행하면 됩니다.

그럼 좀더 자세히 알아 보기로 하겠습니다.

CRect myRECT;                // x1,y1,x2,y2 정보를 지정하는 오브젝트를 확보
GetClientRect(&myRECT);  // 클라이언트 영역의 x1,y1,x2,y2를 myRECT에 설정.
InvalidateRect(&myRECT); // 이 사각형 영역을 다시 그리기 설정

이 처리는 클라이언트 영역 전체의 크기를 myRECT에 설정하여 그 myRECT에서 나타내는 범위를 다시 그리고 있습니다. 혹시 부분적으로 다시 그리기를 한다면,

myRECT.SelRect(0,0,200,200);//클라이언트 영역의 (0,0,)-(200,200)을 지정
9InvalidateRect(&myRECT);//그 사각형 영역을 다시 그리기 지정.

과 같이 하면 되구요, 더욱이 "클라이언트 영역만"을 지우려고 할때에는 사전에 크기를 알아 놓지 않더라도 다음과 같이 아주 간단하 방법으로 지울수 있습니다.

InvalidateRect(NULL);



2) ExtTextOut 이용

제가 알고 있기론 화면 지우는 방법 중에서 가장 빠른 걸로 알고 있습니다.

처음은 똑같습니다.

CRect mRect;
GetClientRect(&mRect);

이 다음 InvalidateRect가 아닌.. ExtTextOut을 씁니다.

  텍스트의 백그라운드 색깔을 칠하고 싶은 화면색깔로 정하고, 빈문자열을 쓰라는 겁니다. 즉(파라미터로 CDC *pDC를 받는다는 가정하에)

pDC->SetBkColor(필요한 색깔);
pDC->ExtTextOut(mRect.left, mRect.top, ETO_OPAQUE, &mRect, "", 0, NULL);

이렇게 빈문자열을 죽~ 라이팅하면 문자열의 배경색으로만 칠해집니다.

말하자면 화면을 지우는 효과이죠.

디폴트를 사용하시겠다면 SetBkColor는 사용하지 않아도 됩니다.

화면을 단일색으로 지우는데는 그 이상 빠른 방법이 없죠.

MFC의 CDC::FillSolidRect도 내부 소스를 보면 ExtTextOut을 사용합니다.

다만 ExtTextOut으로 사각형을 칠했을 때는 DC의 배경색이 바뀐다는 사실을 잊으면 안됩니다.



3) PatBlt 이용

WM_PAINT에서

CPaintDC dc(this);
CRect rect;
GetClientRect(rect);

dc.PatBlt(0, 0, rect.Width(), rect.Height(), WHITENESS);



- the end of this article -

출처 : http://beehone.egloos.com/969621
Comment 0 Trackback 0

Trackback : http://sepoc.tistory.com/trackback/25 관련글 쓰기

Top

꿀뷰3 제작자 인터뷰

1. 꿀뷰를 만드실 때 사용하신 언어와 실례가 안됀다면 꿀뷰프로그램의 총소스코드수를 알고싶어요
-> visual studio / c++ 입니다. 소스라인수는 몇만라인쯤 되겠죠.

2.그리고 만약에 꿀뷰에 간단한 동영상 플레이어 기능을 추가하신다면 가능할까요? 난이도는?
-> 정상적으로는 불가능하죠. 난이도도 높고요. 그냥 미디어 플레이어 콘트롤 쓰면 겉보기는 그럴듯하게 금방 만들수는 있습니다.

3. 역시 mfc나 api를 사용하면 윈도우에서밖엔 작동못하겠죠?..위대하신 빌게이츠동무...꿀뷰는 리눅스에서도 작동하나요?
-> wine 을 쓰면 돌아는 가지만 이거는 답이아니겠죠. 나중에 멀티플랫폼으로 새로 만들어볼 계획은 있습니다만, 몇년후가 될듯하네요.

4. 꿀뷰는 프로그램의 창이 깔끔하고 특이한데, 디자인은 직접하신건가요? 
그것보다 얼마만큼이나 자유로운 GUI를 구현할 수 있는지가 궁금합니다. (예를들어 입체? 3D?) 
-> 디자인은 홈페이지에 써 있는것처럼 다른분들이 도와주셨습니다. 3d 는 불가능하고요.

파일을 드래그앤드롭해서 오픈하는 방법이라던가
설치형식의 프로그램을 작성하는 방법,
마우스 오버를 사용해서 메뉴를 띄운다던가 하는 둥의 사소한(?) 질문들은

-> 드래그&드롭오픈 같은 소소한 부분은 devpia 나 codeproject 같은곳에서 검색하는 능력을 키우면
쉽게 나옵니다. 설치프로그램 만드는건 이 홈페이지의 nsis 를 보시고요.

아 .. 엄습하는 이 두려움은..
일단 API 공부합시다! (책을 샀긴 샀는데 너무 두꺼워 ㅠㅠ)
Comment 0 Trackback 0

Trackback : http://sepoc.tistory.com/trackback/9 관련글 쓰기

Top

prev 1 next