'Resource'에 해당되는 글 3건

  1. 2010.07.21 WinApi 리소스 [String Table]
  2. 2010.07.20 WinApi 리소스 [액셀러레이터]
posted by nsakura 2010. 7. 21. 00:04

윈도우에서는 문자열도 리소스로 취급한다.

많은 문자열을 사용하는 프로그램은

문자열 테이블을 사용하는게 효율적일것이다.


코드는 그냥 이전 포스트에서 사용했던 리소스 예제의 코드를 사용했다.



LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
 HDC hdc;
 PAINTSTRUCT ps;
 TCHAR str[256];

 switch(iMessage){
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 case WM_COMMAND:
  switch(LOWORD(wParam)){
  case ID_NSAKURA:
   MessageBox(hWnd,TEXT("Nsakura 입니다."),TEXT("NSAKURA"),MB_OK);
   break;
  case ID_EXIT:
   MessageBox(hWnd,TEXT("종료 합니다.."),TEXT("EXIT"),MB_OK);
   DestroyWindow(hWnd);
  }
  case WM_PAINT:
   hdc=BeginPaint(hWnd,&ps);
   LoadString(g_Inst,IDS_NSAKURA,str,lstrlen(str));
   TextOut(hdc,10,10,str,lstrlen(str));
   EndPaint(hWnd,&ps);
  return 0;
 }
 
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}

이렇게 코드를 추가하였는데 이번에도 뜸금없이 새로운 함수가 눈에 띄인다.

LoadString함수인데 간단하게 설명하겠다. 그냥 리소스의 문자열 테이블로부터 문자를 가지고 오는 함수이다.

그럼 원형을 살펴보자.

int LoadString(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int nBufferMax);

엇! 첫번째 인자가 이상하다.

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

프록 함수를 보면 인자가 없지만.

우리는 HINSTANCE변수 하나를 전역으로 만들어 두었음을 잊지말며.

WinMain

g_Inst=hInstance;

이부분을 기억해야할 것이다.

요는 첫 번째 인자는 문자열 리소스를 가진 인스턴스 핸들

두 번째 인자는 읽어드릴 문자열 테이블의 ID를

세 번째 인자는 받아온 문자열을 저장할 변수

네 번째 인자는 저장할 변수의 크기를 말한다.

그런데 이렇게 문자열 테이블을 사용하는 이유는 뭘까 그냥 코드상으로 쓰면 안되나.

그냥 교재에서는 이러저래 설명은 되어있지만.

몇 가지 이유를 간추려보면 프로그램이라는건 혼자서 만들수있는 단위는 극히 적다. 있다고하더라도 난잡하다.

왜 난잡할까 특히 이런 문자열 같은경우 안내문인 경우가 많은데. 코딩하랴 저런 사용자적인 부분도 신경쓰랴

그렇다고 전문디자이너보고 코드를 줄수있는 노릇은 아니지 않은가.

그렇기 때문에 이렇게 일의 분담을 효율적으로 할수있으며 두번째는 언어의 버젼을 다르게 만들기 유용하다.

언어의 버젼은 [외국어]를 지칭한다. 지금 a라는 프로그램을 일본에 판다고 했을때 단순히 문자열 테이블만 수정하면

되기 때문이다.

'Computer > Win API' 카테고리의 다른 글

WinApi 그래픽 [색상][펜][브러쉬]  (0) 2010.07.21
WinApi 그래픽 [GetStockObject]  (0) 2010.07.21
WinApi 리소스 [액셀러레이터]  (0) 2010.07.20
WinApi 리소스 [아이콘][커서]  (2) 2010.07.20
WinApi 리소스 [메뉴]  (0) 2010.07.20
posted by nsakura 2010. 7. 20. 23:31

잠시 언급을 했지만 액셀러레이터는 단축키이다.

그럼 어떻게 설정하는지 보자.

리소스 메뉴 소스를 열어서  추가할것이다.




ID에는 액셀러레이터의 아이디인데. 지금 소스는 매뉴도 있으니 매뉴의 NSAKURA와 같은 아이디를 부여했다.

Modifiers에서 조합키를 설정한다 모두 체크되면 or이 아니라 and이기때문에 컨트롤 알트 쉬프트를 누른상태에서 h키를 눌러야 한다.

지금 설정은 컨트롤+h가 되겠다.

Type는 어떤탑으로 키를 쓸것인가 가상키인가 아스키코드인가 선택인데.

가상코드가 종류가 다양함으로 가상코드를 주로 많이 쓴다.

이렇게만 해두면 왠지 모르게 코드 수정없이 해도 동작이 될것 같은데 그건 아니다.

코드도 수정을 해야하는데.

다음과 같이 수정을 한다.

#include <windows.h>
#include "resource.h"

HINSTANCE g_Inst;
LPCTSTR wndName=TEXT("GFP MENU");

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


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd){
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 HACCEL hAccel;
 g_Inst=hInstance;

 WndClass.cbClsExtra=0;
 WndClass.cbWndExtra=0;
 WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
 WndClass.hCursor=LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CURSOR1));
 WndClass.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
 WndClass.hInstance=hInstance;
 WndClass.lpfnWndProc=WndProc;
 WndClass.lpszClassName=wndName;
 WndClass.lpszMenuName=(TCHAR*)IDR_MENU1;
 WndClass.style=CS_HREDRAW|CS_VREDRAW;
 RegisterClass(&WndClass);

 hWnd=CreateWindow(wndName,wndName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,(HMENU)NULL,hInstance,NULL);

 ShowWindow(hWnd,nShowCmd);
 
 hAccel=LoadAccelerators(hInstance,MAKEINTRESOURCE(IDR_ACCELERATOR1));
 while(GetMessage(&Message,NULL,0,0)){
  if(!TranslateAccelerator(hWnd,hAccel,&Message)){
   TranslateMessage(&Message);
   DispatchMessage(&Message);
  }
 }


 return (int)Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
 switch(iMessage){
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 case WM_COMMAND:
  switch(LOWORD(wParam)){
  case ID_NSAKURA:
   MessageBox(hWnd,TEXT("Nsakura 입니다."),TEXT("NSAKURA"),MB_OK);
   break;
  case ID_EXIT:
   MessageBox(hWnd,TEXT("종료 합니다.."),TEXT("EXIT"),MB_OK);
   DestroyWindow(hWnd);
  }
  return 0;
 }
 
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}


일단 액셀러레이터를 사용하기위해서는 액셀러레이터 변수가 필요하다.

HACCEL hAccel;

갑자기 뜸금없이 못보던 함수가 2개가 등장했다. 당황하지 말자.

hAccel=LoadAccelerators(hInstance,MAKEINTRESOURCE(IDR_ACCELERATOR1));

이 함수의 원형을 알아보자

HACCEL LoadAccelerators(HINSTANCE hInstance, LPCTSTR lpTableName);

이 함수로 리소스로로부터 액셀러레이터를 불러온다.

첫 번째 인수는 굳이 설명할 필요가 없을 것같고..

두 번째 인수는 엑셀레이터 테이블을 지정한다.

리소스는 기본적으로 할당할때 정수로 할당하기때문에 MAKEINTRESOURCE사용 하였다.

두 번째 함수는 TranslateAccelerator(hWnd,hAccel,&Message) 인데.

원형을 보자.

int TranslateAccelerator(HWND hWnd, HACCEL hAccTable,LPMSG lpMsg);

이 함수는 키보드 메세지를 WM_COMMAnd 메세지로 변경하여 액셀러레이터가 동작 할 수 있도록 한다. 액셀러레이터가 컨트롤 +H

입력된다고 치면 컨트로+H는 액셀러레이터 이전에 키보드에서 입력을 받았기 때문에 WM_KEYDOWN을 발생할것이다. 그대로 내버려

놔둬버리게 되면 WndProc의 WM_KEYDOWN 메세지 처리 루틴에서 먼저 이 키 값을 처리해버릴 것이다[위의 소스는  WM_KEYDOWN

은 없지만 있다고 생각하자] 즉 TranslateAccelerator함수로 받은 키가 액셀러레이터이라면 리턴으로 1 리턴 [if에선 1이상은

참으로 인식] WM_COMMAND를 발생시킨다.

즉.   if(!TranslateAccelerator(hWnd,hAccel,&Message)){

이부분은 액셀러레이터가 아니라면 기본 작업을 수행한다.

라고 생각하면 간단하다.

ps : TranslateAccelerator가 리턴이 확실히 1인지는 안해봐서 확신이 안서지만 리눅스 기반의 저런기능의
 
함수라면 성공시1 실패시 0

이기 때문에 아마 같지 않을까? 라고 생각한거다 복잡하면 성공하면 TRUE 실패하면 FALSE라고 생각하면 됨.

'Computer > Win API' 카테고리의 다른 글

WinApi 그래픽 [GetStockObject]  (0) 2010.07.21
WinApi 리소스 [String Table]  (0) 2010.07.21
WinApi 리소스 [아이콘][커서]  (2) 2010.07.20
WinApi 리소스 [메뉴]  (0) 2010.07.20
WinApi WM_SIZE  (0) 2010.07.20