※ 요약

아래 이미지와 같이 자식 다이얼로그를 모달리스로 생성하고 띄울때, 부모 다이얼로그(윈도우)가 항상 자식 다이얼로그 밑에 위치하는 경우가 있다. 이는 자식 다이얼로그를 생성할때 부모 Wnd를 어떻게 지정하느냐에 따라 달라지는데 이번 포스트에서는 부모/자식 다이얼로그에 상관없이 활성화된 다이얼로그가 위로 올라오게 하는 방법을 알아보겠다.


※ 소스코드

먼저 소스코드부터 보겠다. Create함수의 두 번째 파라미터의 부모 Wnd를 this로 할 경우 부모 다이얼로그가 항상 자식 다이얼로그 밑에 위치하게 된다. 반대로 CWnd::GetDesktopWindow()로 지정하면 부모/자식 상관없이 활성화된 다이얼로그가 위로 올라오게 된다.



※ 적용 후

this 대신 CWnd::GetDesktopWindow로 지정한 후에는 아래 이미지들 처럼 활성화된 창이 위로 오게 된다.



※ 요약

윈도우의 WM_GETMINMAXINFO 메시지에 대한 포스트다. 이 메시지는 윈도우의 크기나 위치가 변경되었을때 발생하며 보통 윈도우의 최소, 최대 크기를 지정하여 프로그램이 너무 작거나 너무 크게 변경할 수 없도록 해야할때 사용한다. 예제로 만든 프로젝트는 다이얼로그 기반이지만, SDI, MDI 등에서도 적용가능하다.


※ 설명

아래 MFC 프로젝트는 GetMinMaxInfo 설명을 위해 다이얼로그 기반으로 만든 순수 MFC 예제다. 먼저 "클래스 뷰"탭으로 이동하여 다이얼로그 클래스에 마우스 우클릭을 하여 팝업된 메뉴에서 "속성" 항목을 선택한다. (만약 SDI나 MDI 프로젝트일 경우엔 CMainFrame 클래스에 하면 된다.)


메시지 항목을 선택한 후 WM_GETMINMAXINFO 항목을 찾아 Add 해준다.


그럼 아래와 같이 소스코드가 추가되는데, 이곳에 최소/최대 사이즈를 지정해주면 된다.



예제를 위해 임의의 값을 넣어봤다. 아래 예제는 min값과 max값을 모두 넣었는데, 값을 넣을때는 min값만 넣어도 되고, max 값만 넣어도 된다. 필자는 보통 min 값만 넣는 편이다.


컴파일/실행 후 사이즈를 최소로 해본 화면이다. 더 이상 작게 변경할 수 없다.


아래는 최대 사이즈로 된 화면인데, 마찬가지로 더 크게 변경할 수 없다. 


※ 요약
MFC로 개발하다 보면 Alt키나 Ctrl키가 눌렸는지 알아야 할 때가 있다. 이번 포스팅에서는 그 방법을 알아보도록 하겠다. 참고로 전역적으로 하려면 후킹을 통해서 하거나 드라이버 단에서 해야하며, 후킹을 통한 방법은 나중에 올리도록 하겠다.

※ 소스코드



※ 실행예

아래는 실행화면이다. 프로그램 실행후 키를 누르면 그에 해당하는 버튼의 이름을 메시지로 띄우게 했다. 위에서도 언급했지만 프로그램이 트레이에 있거나 최소화 중일때도 Alt키나 Ctrl키가 눌렸는지 확인하려면 후킹을 하면 되며, 후킹 관련은 나중에 올리도록 하겠다.




※MFC 계층도

16년 01월 25일 기준 최신 계층도이다.

출처 - MSDN

 

아래 그림은 CObject로부터 파생된 MFC 클래스들을 나타낸다.

 

아래 그림은 CWnd 및 CCmdTarget로부터 파생된 MFC 클래스들을 나타낸다.

아래 그림은 CObject로부터 파생되지 않은 MFC 클래스들을 나타낸다.

 

※MFC 프로그램 실행 요약

프로젝트 이름이 Temp라고 했을 때, 

각 추적점 및 TRACE를 추가하여 프로그램을 실행시킨 결과는 아래와 같다.

CTempApp::CTempApp()   ------ App 클래스 변수가 전역변수로 선언되어있으므로 제일 먼저 생성자가 호출된다

CTempApp::InitInstance()   ------ MFC 코드에 숨겨진 AfxWinMain함수에서 호출된다. (프로그램의 설정정보 로딩, 파라미터 처리등을 담당)

CTempDoc::CTempDoc(void)   ------ InitInstance()에 의해 Document 객체가 제일먼저 생성된다

CMainFrame::CMainFrame(void)

CMainFrame::LoadFrame()   ------ 윈도우가 생성된다

CMainFrame::PreCreateWindow()

CMainFrame::PreCreateWindow()

CMainFrame::OnCreate()   ------ CMainFrame객체가 생성 및 윈도우가 생성되며 자동으로 WM_CREATE 메시지가 발생하여 호출된다

CMainFrame::OnCreateClient()

CTempView::CTempView()   ------ OnCreateClient()에 의해 View 객체가 생성된다

CTempView::Create()

CTempView::PreCreateWindow()

CTempView::OnCreate()

CTempView::OnShowWindow()   ------ 여기까지 진행하여 클라이언트 뷰를 생성하여 화면에 보여진다

CMainFrame::OnCreateClient() - Return

CMainFrame::OnCreate() - Return   ------ 여기까지 해서 최종적으로 윈도우의 생성이 완료된다

CTempDoc::OnNewDocument()   ------ 새 문서를 만든다

CTempView::OnInitialUpdate()   ------ 새 문서를 만들거나 기존 문서를 열었다면 이 함수를 호출하여 화면 정리 및 적합한 내용을 화면에 표시한다

CMainFrame::OnActivateApp()

CMainFrame::OnActivate()   ------ 응용 프로그램의 최상위 윈도우가 화면에 표시 및 활성화된다

CMainFrame::OnShowWindow()

CTempView::GetDocument()

CTempApp::Run()   ------ 메시지 루프 돌입

------------------------------------------------------------------------------------ 여기까지가 실행 초기화

CMainFrame::OnClose()   ------ 윈도우를 닫았을 대 WM_CLOSE 메시지에 의해 호출

CMainFrame::OnShowWindow()

CMainFrame::OnActivate()

CMainFrame::OnActivateApp()

CMainFrame::DestroyWindow()   ------ OnClose()에 의해 호출된다

CMainFrame::OnDestroy()

CTempView::OnDestroy()   ------ 메인 프레임의 WM_DESTROY 메시지는 자식인 View 객체에도 전달된다

CTempView::PostNcDestroy()

CTempView::~CTempView()

CMainFrame::OnNcDestroy()

CMainFrame::PostNcDestroy()

CMainFrame::~CMainFrame()

CMainFrame::OnNcDestroy() - Return

CTempDoc::~CTempDoc()   ------ 모든 윈도우가 소멸되면 Document 객체도 소멸된다

CMainFrame::OnClose() - Return

CTempApp::ExitInstance()

CTempApp::Run() - Return


출처 - 쿨랜드



Win32 API 나 MFC에서 사용되는 가상 키 코드 ( VK_ ) 입니다.

출처는 마이크로소프트 MSDN입니다.


http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx



VK_LBUTTON
0x01
Left mouse button
VK_RBUTTON
0x02
Right mouse button
VK_CANCEL
0x03

Control-break processing

VK_MBUTTON
0x04

Middle mouse button (three-button mouse)

VK_XBUTTON1
0x05

X1 mouse button

VK_XBUTTON2
0x06

X2 mouse button

-
0x07

Undefined

VK_BACK
0x08

BACKSPACE key

VK_TAB
0x09

TAB key

-
0x0A-0B

Reserved

VK_CLEAR
0x0C

CLEAR key

VK_RETURN
0x0D

ENTER key

-
0x0E-0F

Undefined

VK_SHIFT
0x10

SHIFT key

VK_CONTROL
0x11

CTRL key

VK_MENU
0x12

ALT key

VK_PAUSE
0x13

PAUSE key

VK_CAPITAL
0x14
CAPS LOCK key
VK_KANA
0x15
IME Kana mode
VK_HANGUEL
0x15
IME Hanguel mode (maintained for compatibility; use VK_HANGUL)
VK_HANGUL
0x15
IME Hangul mode
-
0x16
Undefined
VK_JUNJA
0x17
IME Junja mode
VK_FINAL
0x18
IME final mode
VK_HANJA
0x19
IME Hanja mode
VK_KANJI
0x19
IME Kanji mode
-
0x1A
Undefined
VK_ESCAPE
0x1B
ESC key
VK_CONVERT
0x1C
IME convert
VK_NONCONVERT
0x1D
IME nonconvert
VK_ACCEPT
0x1E
IME accept
VK_MODECHANGE
0x1F
IME mode change request
VK_SPACE
0x20
SPACEBAR
VK_PRIOR
0x21
PAGE UP key
VK_NEXT
0x22
PAGE DOWN key
VK_END
0x23
END key
VK_HOME
0x24
HOME key
VK_LEFT
0x25
LEFT ARROW key
VK_UP
0x26
UP ARROW key
VK_RIGHT
0x27
RIGHT ARROW key
VK_DOWN
0x28
DOWN ARROW key
VK_SELECT
0x29
SELECT key
VK_PRINT
0x2A
PRINT key
VK_EXECUTE
0x2B
EXECUTE key
VK_SNAPSHOT
0x2C
PRINT SCREEN key
VK_INSERT
0x2D
INS key
VK_DELETE
0x2E
DEL key
VK_HELP
0x2F
HELP key
0x300 key
0x311 key
0x322 key
0x333 key
0x344 key
0x355 key
0x366 key
0x377 key
0x388 key
0x399 key
-
0x3A-40
 
Undefined
 
0x41
 
A key
 
0x42
 
B key
 
0x43
 
C key
 
0x44
 
D key
 
0x45
 
E key
 
0x46
 
F key
 
0x47
 
G key
 
0x48
 
H key
 
0x49
 
I key
 
0x4A
 
J key
 
0x4B
 
K key
 
0x4C
 
L key
 
0x4D
 
M key
 
0x4E
 
N key
 
0x4F
 
O key
 
0x50
 
P key
 
0x51
 
Q key
 
0x52
 
R key
 
0x53
 
S key
 
0x54
 
T key
 
0x55
 
U key
 
0x56
 
V key
 
0x57
 
W key
 
0x58
 
X key
 
0x59
 
Y key
 
0x5A
 
Z key
 
VK_LWIN
0x5B
 
Left Windows key (Natural keyboard)
 
VK_RWIN
0x5C
 
Right Windows key (Natural keyboard)
 
VK_APPS
0x5D
 
Applications key (Natural keyboard)
 
-
0x5E
 
Reserved
 
VK_SLEEP
0x5F
 
Computer Sleep key
 
VK_NUMPAD0
0x60
 
Numeric keypad 0 key
 
VK_NUMPAD1
0x61
 
Numeric keypad 1 key
 
VK_NUMPAD2
0x62
 
Numeric keypad 2 key
 
VK_NUMPAD3
0x63
 
Numeric keypad 3 key
 
VK_NUMPAD4
0x64
 
Numeric keypad 4 key
 
VK_NUMPAD5
0x65
 
Numeric keypad 5 key
 
VK_NUMPAD6
0x66
 
Numeric keypad 6 key
 
VK_NUMPAD7
0x67
 
Numeric keypad 7 key
 
VK_NUMPAD8
0x68
 
Numeric keypad 8 key
 
VK_NUMPAD9
0x69
 
Numeric keypad 9 key
 
VK_MULTIPLY
0x6A
 
Multiply key
 
VK_ADD
0x6B
 
Add key
 
VK_SEPARATOR
0x6C
 
Separator key
 
VK_SUBTRACT
0x6D
 
Subtract key
 
VK_DECIMAL
0x6E
 
Decimal key
 
VK_DIVIDE
0x6F
 
Divide key
 
VK_F1
0x70
 
F1 key
 
VK_F2
0x71
 
F2 key
 
VK_F3
0x72
 
F3 key
 
VK_F4
0x73
 
F4 key
 
VK_F5
0x74
 
F5 key
 
VK_F6
0x75
 
F6 key
 
VK_F7
0x76
 
F7 key
 
VK_F8
0x77
 
F8 key
 
VK_F9
0x78
 
F9 key
 
VK_F10
0x79
 
F10 key
 
VK_F11
0x7A
 
F11 key
 
VK_F12
0x7B
 
F12 key
 
VK_F13
0x7C
 
F13 key
 
VK_F14
0x7D
 
F14 key
 
VK_F15
0x7E
 
F15 key
 
VK_F16
0x7F
 
F16 key
 
VK_F17
0x80
 
F17 key
 
VK_F18
0x81
 
F18 key
 
VK_F19
0x82
 
F19 key
 
VK_F20
0x83
 
F20 key
 
VK_F21
0x84
 
F21 key
 
VK_F22
0x85
 
F22 key
 
VK_F23
0x86
 
F23 key
 
VK_F24
0x87
 
F24 key
 
-
0x88-8F
 
Unassigned
 
VK_NUMLOCK
0x90
 
NUM LOCK key
 
VK_SCROLL
0x91
 
SCROLL LOCK key
 
0x92-96
 
OEM specific
 
-
0x97-9F
 
Unassigned
 
VK_LSHIFT
0xA0
 
Left SHIFT key
 
VK_RSHIFT
0xA1
 
Right SHIFT key
 
VK_LCONTROL
0xA2
 
Left CONTROL key
 
VK_RCONTROL
0xA3
 
Right CONTROL key
 
VK_LMENU
0xA4
 
Left MENU key
 
VK_RMENU
0xA5
 
Right MENU key
 
VK_BROWSER_BACK
0xA6
 
Browser Back key
 
VK_BROWSER_FORWARD
0xA7
 
Browser Forward key
 
VK_BROWSER_REFRESH
0xA8
 
Browser Refresh key
 
VK_BROWSER_STOP
0xA9
 
Browser Stop key
 
VK_BROWSER_SEARCH
0xAA
 
Browser Search key
 
VK_BROWSER_FAVORITES
0xAB
 
Browser Favorites key
 
VK_BROWSER_HOME
0xAC
 
Browser Start and Home key
 
VK_VOLUME_MUTE
0xAD
 
Volume Mute key
 
VK_VOLUME_DOWN
0xAE
 
Volume Down key
 
VK_VOLUME_UP
0xAF
 
Volume Up key
 
VK_MEDIA_NEXT_TRACK
0xB0
 
Next Track key
 
VK_MEDIA_PREV_TRACK
0xB1
 
Previous Track key
 
VK_MEDIA_STOP
0xB2
 
Stop Media key
 
VK_MEDIA_PLAY_PAUSE
0xB3
 
Play/Pause Media key
 
VK_LAUNCH_MAIL
0xB4
 
Start Mail key
 
VK_LAUNCH_MEDIA_SELECT
0xB5
 
Select Media key
 
VK_LAUNCH_APP1
0xB6
 
Start Application 1 key
 
VK_LAUNCH_APP2
0xB7
 
Start Application 2 key
 
-
0xB8-B9
 
Reserved
 
VK_OEM_1
0xBA
 
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the ';:' key
 
VK_OEM_PLUS
0xBB
 
For any country/region, the '+' key
 
VK_OEM_COMMA
0xBC
 
For any country/region, the ',' key
 
VK_OEM_MINUS
0xBD
 
For any country/region, the '-' key
 
VK_OEM_PERIOD
0xBE
 
For any country/region, the '.' key
 
VK_OEM_2
0xBF
 
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the '/?' key
 
VK_OEM_3
0xC0
 
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the '`~' key
 
-
0xC1-D7
 
Reserved
 
-
0xD8-DA
 
Unassigned
 
VK_OEM_4
0xDB
 
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the '[' key
 
VK_OEM_5
0xDC
 
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the '' key
 
VK_OEM_6
0xDD
 
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the '] ' key
 
VK_OEM_7
0xDE
 
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the 'single-quote/double-quote' key
 
VK_OEM_8
0xDF
 
Used for miscellaneous characters; it can vary by keyboard.
 
-
0xE0
 
Reserved
 
0xE1
 
OEM specific
 
VK_OEM_102
0xE2
 
Either the angle bracket key or the backslash key on the RT 102-key keyboard
 
0xE3-E4
 
OEM specific
 
VK_PROCESSKEY
0xE5
 
IME PROCESS key
 
0xE6
 
OEM specific
 
VK_PACKET
0xE7
 
Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in  KEYBDINPUT  SendInput , WM_KEYDOWN , and  WM_KEYUP
 
-
0xE8
 
Unassigned
 
0xE9-F5
 
OEM specific
 
VK_ATTN
0xF6
 
Attn key
 
VK_CRSEL
0xF7
 
CrSel key
 
VK_EXSEL
0xF8
 
ExSel key
 
VK_EREOF
0xF9
 
Erase EOF key
 
VK_PLAY
0xFA
 
Play key
 
VK_ZOOM
0xFB
 
Zoom key
 
VK_NONAME
0xFC
 
Reserved
 
VK_PA1
0xFD
 
PA1 key
 
VK_OEM_CLEAR
0xFE
 
Clear key
 







아래는 MFC 프로젝트에 디버깅을 위한 콘솔 창을 띄운 모습입니다. (아래 프로그램은 로또 프로그램)



사실 MFC의 경우는 아래 캡쳐와 같이 TRACE 매크로를 통해 로그(디버깅 메시지)를 확인할 수 있지만

Win32 API의 경우는 TRACE 매크로가 없으며, 있어도 TRACE보다는 printf로 출력하는 게 더 편할 때도 있어서 

가끔 콘솔창을 이용합니다.



TRACE보다 printf로 출력하면 더 편한 몇 가지 이유로는

 - printf의 경우 서식문자를 쓸수 있다.  ex) printf( "에러 번호 : %d, 에러 내용 : %s", nErrorNum, GetLastError() );

 - TRACE의 경우 출력 창에 내용이 표시되는데, TRACE 내용 말고도 잡다한 내용이 많다.

 - 콘솔 창의 경우는 내가 남긴 로그만 볼 수 있어서 깔끔하다.




제가 아는 콘솔창 띄우는 방법은 2가지가 있습니다. ( 그 외 AllocConsole 등도 있음 )

아래와 같이 프로젝트 속성에서 창을 띄우는 방법이 있고



아래의 소스를 추가하는 방법이 있습니다.

아래 소스는 아시다시피 디버깅 모드일 때만 콘솔창이 뜨도록 한 겁니다.

#ifdef _DEBUG #pragma comment(linker, "/entry:WinMainCRTStartup /subsystem:console") #endif


+ Recent posts