1. 메뉴바 => 팝업 메뉴 => 메뉴 아이템
- 메뉴바도 하나의 윈도우기 때문에 구조체를 갖는다. ( MENUINFO )
- 마찬가지로 팝업메뉴도 하나의 윈도우이기 때문에 구조체를 갖는다. ( MENUITEMINFO )
2. 적재 방법
- 윈도우 클래스에 바로 등록한다. wc.lpszMenuName
- CreateWindowEx 10번쨰 인자에 준다. HMENU( 핸들을 등록해준다. )
- 윈도우 생성 후 SetMenu() GetMenu() 로 등록해준다.
- 임의로 메뉴바를 추가 했을 때는 rc에서 아이디추가, 다음 가르킬 ID를 변경 해줘야 한다.
3. 메뉴윈도우가 부모에게 보내주는 메시지.
- WM_INITMENU
- WM_INITPOPUPMENU : 'v' 메뉴항목의 체크작업 해줄 수 있다.
- WM_MENUSELECT : 메뉴설명을 상태방에 추가 할 수 있다.
- WM_COMMAND : 메뉴를 선택 했을 때 메뉴의 메시지 처리함수에서 부모에게 메세지를 보내준다.
4. ModifyMenu
- 최근 사용한 파일을 표현할 수도 있다.(추후구현) : AppendMenu, DrawMenuBar (레지스터리 참조)
- 윈도우즈는 모든 구성요소를 구조체로 만든 Object-Based 이므로 구조체만 수정해주면 된다.
5. 메뉴 OWNERDRAW
- 색변경
1) WM_CTLCOLOR 에서 처리한다.
2) OWERDRAW : 메뉴, 기본컨트롤 - 결국 UI만 대신 그려주는 역할. 동작은 클래스내부에서 처리한다.
3) CustomDraw : 공용 컨트롤에 적용
- MF_OWNERDRAW : 속성으로 변경을 한다. ( ModifyMenu )
- WM_MEASUREITEM : 그릴 항목의 크기를 지정해달라는 MSG를 OS가 보낸다. 열릴때 최초 1회발생
- WM_DRAWITEM : 사용자가 그려 주라는 메시지로 HDC(lParam) 와 기타 모든 정보가 넘어온다.
- LPDRAWITEMSTRUCT 현재 state를 조사할 수 있다.
6. Context Menu
- WM_RBUTTONUP 생성 => 처리 하지 않는 메시지는 DefProc로 보내줘야 한다.
- WM_CONTEXTMENU
1) Context메뉴 리소스 제작시 _MENU로 이름을 주어 구분한다. OWNERDRAW를 적용받지 못한다.
- 스크린 좌표로 넘어온다.( 클라이언트좌표로 변환 )
- WM_COMMAND에서 명령을 처리하면 된다.
- 메뉴바도 하나의 윈도우기 때문에 구조체를 갖는다. ( MENUINFO )
- 마찬가지로 팝업메뉴도 하나의 윈도우이기 때문에 구조체를 갖는다. ( MENUITEMINFO )
2. 적재 방법
- 윈도우 클래스에 바로 등록한다. wc.lpszMenuName
- CreateWindowEx 10번쨰 인자에 준다. HMENU( 핸들을 등록해준다. )
- 윈도우 생성 후 SetMenu() GetMenu() 로 등록해준다.
- 임의로 메뉴바를 추가 했을 때는 rc에서 아이디추가, 다음 가르킬 ID를 변경 해줘야 한다.
3. 메뉴윈도우가 부모에게 보내주는 메시지.
- WM_INITMENU
- WM_INITPOPUPMENU : 'v' 메뉴항목의 체크작업 해줄 수 있다.
- WM_MENUSELECT : 메뉴설명을 상태방에 추가 할 수 있다.
- WM_COMMAND : 메뉴를 선택 했을 때 메뉴의 메시지 처리함수에서 부모에게 메세지를 보내준다.
4. ModifyMenu
- 최근 사용한 파일을 표현할 수도 있다.(추후구현) : AppendMenu, DrawMenuBar (레지스터리 참조)
- 윈도우즈는 모든 구성요소를 구조체로 만든 Object-Based 이므로 구조체만 수정해주면 된다.
5. 메뉴 OWNERDRAW
- 색변경
1) WM_CTLCOLOR 에서 처리한다.
2) OWERDRAW : 메뉴, 기본컨트롤 - 결국 UI만 대신 그려주는 역할. 동작은 클래스내부에서 처리한다.
3) CustomDraw : 공용 컨트롤에 적용
- MF_OWNERDRAW : 속성으로 변경을 한다. ( ModifyMenu )
- WM_MEASUREITEM : 그릴 항목의 크기를 지정해달라는 MSG를 OS가 보낸다. 열릴때 최초 1회발생
- WM_DRAWITEM : 사용자가 그려 주라는 메시지로 HDC(lParam) 와 기타 모든 정보가 넘어온다.
- LPDRAWITEMSTRUCT 현재 state를 조사할 수 있다.
6. Context Menu
- WM_RBUTTONUP 생성 => 처리 하지 않는 메시지는 DefProc로 보내줘야 한다.
- WM_CONTEXTMENU
1) Context메뉴 리소스 제작시 _MENU로 이름을 주어 구분한다. OWNERDRAW를 적용받지 못한다.
- 스크린 좌표로 넘어온다.( 클라이언트좌표로 변환 )
- WM_COMMAND에서 명령을 처리하면 된다.
7. Dialog 공용 컨트롤 ( #32770 에 등록 )
- DialogBox() => CreateWindow를 내부적으로 호출한다. 자기만의 메시지 루프를 가진다.
- DlgProc() 사용자정의 함수로 메시지를 전달 해주게 된다.
- 전달해 주는 메시지는 정해 져있다.( WndProc 과 엇비슷 )
- WM_INITDIALOG : WM_CREATE를 수행한 후에 초기상태를 정하라는 메시지!!!
- 특정키를 막거나 메시지를 가로 채려면 여기서 하는게 아니라 서브클래싱 해줘야 한다.!!
DlgProc()
EndDialog() // 내부적으로 미리 약속되어 있는
// 탈출작업을 한다.
WndProc()
: DialogBox : Blocking 된다.
DialogBox()
1) CreateWindowEx() 다이얼로그 생성
2) EnableWindow( 부모, FALSE ) 부모 블럭
3) WM_INITDIALOG 발생
4) 메시지 루프 Dispatch로 메시지 받아옴
5) 부모 Enable 후 다이얼로그 파괴
4)부가설명 - 메시지 박스가 내부적으로 메시지 루프를 갖는것과 같다. 이때 Dispatch 에서 Message를 DlgProc으로 보내준다.
- DialogBox는 내부적으로 DialogBoxParam을 호출 한다 lParam을 0L로 주는것에 불과한 매크로이다!! 호환성위해..
8. Dialog값 꺼내오기
- 핸들을 알아야 윈도우의 값을 얻어오므로 ID로부터 핸들을 얻어야 한다. GetDlgItem( ID ) 로 얻어온다!!
- GetDlgItem + GetWindowLong = GetDlgItemText 해당 컨트롤로부터 int값을 buf로 읽어 올수 있다.
- DialogBoxParam() : lParam으로 특정데이터를 넘길 수 있다. 전역변수 대신에 포인터로 접근하는것!!
- 이를 사용하면 Dialog에서 사용한 컨트롤의 값들을 lParam에 저장해두면 부모가 값을 읽어오는것이다.
9 모달리스
- 생성과정 : DialogBox 를 CreateDialog 로 생성 해줘야 한다.
- 파괴는 EndDialog => DestroyWindow() 취소버튼을 눌렀을때 파괴~
- 이방식은 DlgProc() 에서 사용자정의 메시지를 WndProc() 로 보내 작업을 수행하도록 할 수 있다.
- 메시지 루프가 없으므로 부모윈도우가 같은 메시지 루프를 사용한다.
- 그러므로 Dialog에서 특정키등을 가로채서 모달리스에 전달 하고자 할 떄는 메시지루프를 수정한다.
- DialogBox() => CreateWindow를 내부적으로 호출한다. 자기만의 메시지 루프를 가진다.
- DlgProc() 사용자정의 함수로 메시지를 전달 해주게 된다.
- 전달해 주는 메시지는 정해 져있다.( WndProc 과 엇비슷 )
- WM_INITDIALOG : WM_CREATE를 수행한 후에 초기상태를 정하라는 메시지!!!
- 특정키를 막거나 메시지를 가로 채려면 여기서 하는게 아니라 서브클래싱 해줘야 한다.!!
DlgProc()
EndDialog() // 내부적으로 미리 약속되어 있는
// 탈출작업을 한다.
WndProc()
: DialogBox : Blocking 된다.
DialogBox()
1) CreateWindowEx() 다이얼로그 생성
2) EnableWindow( 부모, FALSE ) 부모 블럭
3) WM_INITDIALOG 발생
4) 메시지 루프 Dispatch로 메시지 받아옴
5) 부모 Enable 후 다이얼로그 파괴
4)부가설명 - 메시지 박스가 내부적으로 메시지 루프를 갖는것과 같다. 이때 Dispatch 에서 Message를 DlgProc으로 보내준다.
- DialogBox는 내부적으로 DialogBoxParam을 호출 한다 lParam을 0L로 주는것에 불과한 매크로이다!! 호환성위해..
8. Dialog값 꺼내오기
- 핸들을 알아야 윈도우의 값을 얻어오므로 ID로부터 핸들을 얻어야 한다. GetDlgItem( ID ) 로 얻어온다!!
- GetDlgItem + GetWindowLong = GetDlgItemText 해당 컨트롤로부터 int값을 buf로 읽어 올수 있다.
- DialogBoxParam() : lParam으로 특정데이터를 넘길 수 있다. 전역변수 대신에 포인터로 접근하는것!!
- 이를 사용하면 Dialog에서 사용한 컨트롤의 값들을 lParam에 저장해두면 부모가 값을 읽어오는것이다.
9 모달리스
- 생성과정 : DialogBox 를 CreateDialog 로 생성 해줘야 한다.
- 파괴는 EndDialog => DestroyWindow() 취소버튼을 눌렀을때 파괴~
- 이방식은 DlgProc() 에서 사용자정의 메시지를 WndProc() 로 보내 작업을 수행하도록 할 수 있다.
- 메시지 루프가 없으므로 부모윈도우가 같은 메시지 루프를 사용한다.
- 그러므로 Dialog에서 특정키등을 가로채서 모달리스에 전달 하고자 할 떄는 메시지루프를 수정한다.
if ( !IsWindow( g_hDlg ) || !IsDialogMessage( g_hDlg, &msg ))
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}