MFC 사용하다보면 자주 만나는 경고... 메시지.. 찾아보면 다음과 같이 해결책을 제시하고 있네...
[출처] http://msdn.microsoft.com/ko-kr/library/6wtdswk0(VS.80).aspx

링커 도구 경고 LNK4098
오류 메시지
'library' defaultlib가 다른 라이브러리와 충돌합니다. /NODEFAULTLIB:library를 사용하십시오.
defaultlib 'library' conflicts with use of other libs; use /NODEFAULTLIB:library
호환되지 않는 라이브러리에 링크하려고 했습니다.
Note참고

런타임 라이브러리에는 여러 형식이 혼합 사용되지 않도록 하는 지시문이 들어 있는데 여러 형식이나 디버그/비디버그 버전의 런타임 라이브러리를 동일한 프로그램에서 사용하려고 하면 이 경고가 발생합니다. 예를 들어, 어떤 종류의 런타임 라이브러리를 사용하는 파일을 컴파일하고 다른 종류의 런타임 라이브러리를 사용하는 파일을 컴파일한 다음(예: 단일 스레드 라이브러리와 다중 스레드 라이브러리) 이 둘을 링크시키려고 하면 이 경고가 발생합니다. 동일한 런타임 라이브러리를 사용하는 소스 파일을 컴파일해야 합니다. 자세한 내용은 런타임 라이브러리 사용(/MD/MT/LD) 컴파일러 옵션을 참조하십시오.

링커의 /VERBOSE:LIB 스위치를 사용하여 링커가 검색 중인 라이브러리를 확인할 수 있습니다. 예를 들어, LNK4098이 발생하여 단일 스레드된 비디버그 런타임 라이브러리를 사용하는 실행 파일을 만들려는 경우에는 /VERBOSE:LIB 옵션을 사용하여 링커에서 검색 중인 라이브러리를 확인하십시오. 링커는 검색한 라이브러리로 LIBC.lib를 출력하며 LIBCMT.lib, MSVCRT.lib, LIBCD.lib, LIBCMTD.lib 또는 MSVCRTD.lib는 출력하지 않습니다. 무시할 각 라이브러리에 대해 /NODEFAULTLIB를 사용하여 링커가 잘못된 런타임 라이브러리를 무시하도록 할 수 있습니다.

다음 표는 사용할 런타임 라이브러리에 따라 무시해야 하는 라이브러리를 보여 줍니다.

사용할 런타임 라이브러리무시해야 하는 라이브러리

단일 스레드(libc.lib)

libcmt.lib, msvcrt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib

다중 스레드(libcmt.lib)

libc.lib, msvcrt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib

DLL을 사용하는 다중 스레드(msvcrt.lib)

libc.lib, libcmt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib

디버그 단일 스레드(libcd.lib)

libc.lib, libcmt.lib, msvcrt.lib, libcmtd.lib, msvcrtd.lib

디버그 다중 스레드(libcmtd.lib)

libc.lib, libcmt.lib, msvcrt.lib, libcd.lib, msvcrtd.lib

DLL을 사용하는 디버그 다중 스레드(msvcrtd.lib)

libc.lib, libcmt.lib, msvcrt.lib, libcd.lib, libcmtd.lib

예를 들어, 이 경고가 발생한 경우와 비디버그, 단일 스레드 버전의 런타임 라이브러리를 사용하는 실행 파일을 만들려는 경우에는 링커에 다음 옵션을 사용하면 됩니다.

/NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:libcd.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrtd.lib

void DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, LONG xStart, LONG yStart, COLORREF cTransparentColor)  
{  
BITMAP bm;  
COLORREF cColor;  
HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;  
HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;  
HDC hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;  
POINT ptSize;  
/* 초기화 작업 */
hdcTemp = CreateCompatibleDC(hdc);  
SelectObject(hdcTemp, hBitmap); // 비트맵 선택

GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);  
ptSize.x = bm.bmWidth; // 비트맵 가로 크기 
ptSize.y = bm.bmHeight; // 비트맵 세로 크기
DPtoLP(hdcTemp, &ptSize, 1); // 디바이스를 논리적 위치로 변경

// 작업용 DC 생성
hdcBack = CreateCompatibleDC(hdc);  
hdcObject = CreateCompatibleDC(hdc);  
hdcMem = CreateCompatibleDC(hdc);  
hdcSave = CreateCompatibleDC(hdc);  

// 흑백 연산 (and,or연산)에 필요한 비트맵 생성 
bmAndBack = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);  
bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);  
// 작업용 비트맵들 생성 
bmAndMem = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);  
bmSave = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);  

// 각 비트맵 삭제 위한 old 비트맵 생성 
bmBackOld = (HBITMAP)SelectObject(hdcBack, bmAndBack);  
bmObjectOld = (HBITMAP)SelectObject(hdcObject, bmAndObject);  
bmMemOld = (HBITMAP)SelectObject(hdcMem, bmAndMem);  
bmSaveOld = (HBITMAP)SelectObject(hdcSave, bmSave);  

//그려질 DC와 생성된 임시DC의 맵핑 모드 일치화 
SetMapMode(hdcTemp, GetMapMode(hdc));  

// 원본 보전 작업
BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);  

// 투명화 시킬 색을 Tempdc의 배경색으로 설정,
// 이때 SetBkColor의 리턴 값으로 원본 색 저장
cColor = SetBkColor(hdcTemp, cTransparentColor);  

/* 주어진 비트맵의 투명색(BkColor로 지정된)은 힌색으로,
나머지는 검은색으로하여 BlackWhitedc_1에 저장 */
BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0,   
SRCCOPY);  

// 배경 색을 원본 색상 DC를 가져오기
SetBkColor(hdcTemp, cColor);  

// BlackWhitedc_1를 이용 투명 영역(검은색), 비투명 영역(힌색)으로 된 DC생성 
BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0,   NOTSRCCOPY);  

// 그려질 hdc에서 비트맵이 위치할 곳의 배경을 작업용 DC로 이동 
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart, SRCCOPY);  
//BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, 0, 0, SRCCOPY);  

// 그려질 배경과 and 연산을 통해 배경투명구현(힌색 소멸), 비투명 영역은 검은 색으로
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);  

// 주어진 비트맵과 and 연산을 통해 투명부분(검은색으로), 비투명은 그대로
BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);  

// 위에서 만든 2개의 DC(Workdc, Tempdc)의 or 연산을 통해 두 DC결합 
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);  

//  결과를 표시
BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY);  

//  원본을 임시 DC에 복구
BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);  

// 메모리에 있는 각 비트맵 삭제
DeleteObject(SelectObject(hdcBack, bmAndBack));  
DeleteObject(SelectObject(hdcObject,bmAndObject));  
DeleteObject(SelectObject(hdcMem, bmAndMem));  
DeleteObject(SelectObject(hdcSave, bmSave));  
DeleteObject(SelectObject(hdcBack, bmBackOld));  
DeleteObject(SelectObject(hdcObject,bmObjectOld));  
DeleteObject(SelectObject(hdcMem, bmMemOld));  
DeleteObject(SelectObject(hdcSave, bmSaveOld));  

// 각 DC삭제 
DeleteDC(hdcBack);  
DeleteDC(hdcObject);
DeleteDC(hdcMem);    
DeleteDC(hdcSave);  
DeleteDC(hdcTemp);  
DeleteDC(hdc); // 자신의 DC를 삭제하지 않으면 GDI 객체는 계속 늘어나게 된다..
 }  


/// 사용 예시..
DrawTransparentBitmap(::GetDC(((CStatic*)GetDlgItem(컨트롤))->GetSafeHwnd()), (BMP), 0, 0, 색상);

// 미리 정의해 놓고 사용하면 좀더 편리함...
#define TRANS_BITMAP(CTRL, BMP); DrawTransparentBitmap(::GetDC(((CStatic*)GetDlgItem(CTRL))->GetSafeHwnd()), (BMP), 0, 0, BLACK);

검색중 찾은 자료이다. 구글 번역으로 돌려서 번역이 매끄럽지 못하다.. 추후 시간 되는대로 수정 예정...


원문 : http://blog.csdn.net/andylin02/archive/2007/07/28/1712984.aspx

대화 상자 및 Windows 팁 

저자 : lixiaosan 
날짜 : 2006년 4월 11일 

계속해서, 여기에 기사를 업데이 트를 방문하시기 바랍니다 

참고 : 대화 상자에 다음 코드를 클래스로, 예를 들어위한, CTest6Dlg 전화 

1. 작업 표시줄의 숨겨진 대화 상자

ModifyStyleEx (WS_EX_APPWINDOW, WS_EX_TOOLWINDOW); 


2. 최상위 윈도우에 대한 대화 상자를 만들려면

SetWindowPos (&이 - "wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 


실행 있음, 버튼을 최소화 최대화하기 위해 추가 3. - 시간

SetWindowLong (이 - "m_hWnd, GWL_STYLE, 
GetWindowLong (이 - "m_hWnd, GWL_STYLE) | 
WS_MINIMIZEBOX | WS_MAXIMIZEBOX); 
UpdateWindow (); 



4. 오른쪽 상단 모서리에있는 대화 상자를 닫습 버튼을 클릭 할 수 있으려면


OnInitDialog에 있음 

방법 1 : 
CMenu * 메뉴 = GetSystemMenu (가 FALSE); 
메뉴에서 "ModifyMenu (SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); 

방법 2 : 
CMenu * 메뉴 = GetSystemMenu (가 FALSE); 
메뉴에서 "EnableMenuItem (SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); 


5.되면 대화 상자에서, 화면의 일부가 밖으로 모든 대화 상자 표시

SendMessage (DM_REPOSITION); 


6. 마우스 모양을 변경하려면,


메시지 맵 함수 WM_SETCURSOR 추가 

BOOL CTest6Dlg : : OnSetCursor (CWnd * pWnd, UINT nHitTest, UINT 메시지) 
( 
SetCursor (AfxGetApp () - "LoadStandardCursor (IDC_HELP)); 

반환 0; 
) 


7. 배경색과 대화 상자의 텍스트 색상을 변경하려면,


InitInstance에서 있음 CTest6App 추가 

SetDialogBkColor (RGB (255,0,0), RGB (0,255,0)); 


8. 대화 상자에서 아이콘을 변경하려면 캡션


프로젝트 가져오기 고객님의 아이콘 리소스를 원래의 리소스 IDR_MAINFRAME 제거에 대한 ID가 ID의 새 아이콘 이름 IDR_MAINFRAME 


9. 메인 대화 상자에서 로그인하기 전에 대화 상자가 표시됩니다 표시


BOOL CTest6App : : InitInstance에서 () 
( 
//... 
nResponse int; 
CLoginDlg loginDlg; 

nResponse = loginDlg.DoModal (); 
면 (== IDOK) nResponse 
( 
) 
면 (== IDCANCEL)를 nResponse 
( 
FALSE를 반환; 
) 

CTest6Dlg DLG; 
m_pMainWnd = &dlg; 
int nResponse = dlg.DoModal (); 
면 (== IDOK) nResponse 
( 
) 
다른면 (== IDCANCEL)를 nResponse 
( 
) 
FALSE를 반환; 
) 

그럼 CLoginDlg 오, OnOK 대화 상자의 과부하 (), 조건은 판사 
무효 CLoginDlg : : OnOK () 
( 
만약 (조건)를 만났지 
CDialog : : OnOK (); 
그 밖의 
AfxMessageBox (_T ( "잘못된 비밀 번호 !")); 
) 



10. 대화 상자에서 도구 모음을 추가하려면


방법 1 : OnInitDialog에 다음과 같은 코드를 추가합니다 

만약 (! (이) | |! m_wndToolBar.LoadToolBar (IDR_TOOLBAR1)) m_wndToolBar.Create 
( 
TRACE0 ( "대화 상자 도구 모음을 만들려을 \ n") 실패; 
EndDialog (IDCANCEL)를; 
) 

CRect rcClientOld; / / 이전 클라이언트 영역을 RECT 
CRect rcClientNew; / / 클라이언트 RECT 후 툴바에 추가 
GetClientRect (rcClientOld); / / 
/ / 위치를 조정하고 윈도우의 클라이언트 영역에 컨트롤 막대 크기를 호출 
/ / reposQuery FLAG 정말 툴바 traw하지 않습니다. 그것은 단지 계산 않습니다. 
그래서 우리는 수학의 휴식을 할 수있어 / / 그리고 rcClientNew에 새 값을 ClientRect 선수야. 
/ / 다시 크기 RECT 계산 
RepositionBars (AFX_IDW_CONTROLBAR_FIRST, 
AFX_IDW_CONTROLBAR_LAST, 
0 
reposQuery, 
rcClientNew); 

그래서 Tollbar 그들이 사실을 은폐하지 않습니다 / / 모든 자식 윈도우 (컨트롤) 지금 필요로 이동할 수있습니다.
/ / 모든 자식 윈도우의 이동됩니다 툴바에 의해 보호되고 피하기 위해 
/ / 모든 자식 이동 Offest Tollbar를 추가한 후 컨트롤 
/ / 계산 거리를 이동하려면 
CPoint ptOffset (rcClientNew.left - rcClientOld.left, 
rcClientNew.top - rcClientOld.top); 

CRect rcChild; 
CWnd * pwndChild = GetWindow (GW_CHILD); / / 아이 창이 
(pwndChild) 동안 / 모든 자식 창 핸들 / 
( 
/ / 모든 자식 창을 이동 
pwndChild - "GetWindowRect (rcChild); 
ScreenToClient (rcChild); 
rcChild.OffsetRect (ptOffset); 
pwndChild - "MoveWindow (rcChild, FALSE를); 
pwndChild - pwndChild = "GetNextWindow (); 
) 

CRect rcWindow; 
GetWindowRect (rcWindow); / / 얻을 대화 상자 RECT 
rcWindow.right + = rcClientOld.Width () - rcClientNew.Width (); / / 대화 상자에서 크기를 수정 
rcWindow.bottom + = rcClientOld.Height () - rcClientNew.Height (); 
MoveWindow (rcWindow, FALSE를); / / 창 다시 그리기 

RepositionBars (AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); 

방법 2 : 

http://www.codeproject.com/dialog/dlgtoolstatusbar.asp 


11. 대화 상자, 주변을 최소화 및 복원을 극대화 이벤트에 응답하려면


방법 1 : WM_SYSCOMMAND 메시지 맵 기능 추가 

무효 CTest6Dlg : : OnSysCommand (UINT 꾸벅꾸벅, lparam lParam) 
( 
((꾸벅꾸벅 & 0xFFF0) == IDM_ABOUTBOX 경우) 
( 
CAboutDlg dlgAbout; 
dlgAbout.DoModal (); 
) 
그 밖의 
( 
(꾸벅꾸벅 == SC_MAXIMIZE 경우) 
( 
AfxMessageBox (_T ( "최대화")); 
) 
다른 경우 (꾸벅꾸벅 == SC_MINIMIZE) 
( 
AfxMessageBox (_T ( "최소화")); 
) 
다른 경우 (꾸벅꾸벅 == SC_CLOSE) 
( 
AfxMessageBox (_T ( "닫기")); 
) 

CDialog : : OnSysCommand (lParam) 꾸벅꾸벅; 
) 

방법 2 : WM_SIZE 메시지가지도 기능을 추가 

무효 CTest6Dlg : : OnSize (UINT nType, int CX는, int 사) 
( 
CDialog : : OnSize (nType, CX는, 사); 

(nType == SIZE_MAXIMIZED 경우) 
( 
AfxMessageBox (_T ( "최대화")); 
) 
다른 경우 (nType == SIZE_MINIMIZED) 
( 
AfxMessageBox (_T ( "최소화")); 
) 
다른 경우 (nType == SIZE_RESTORED) 
( 
AfxMessageBox (_T ( "")) 복원; 
) 
) 


12. 코드 창을 최소화, 닫기를 극대화 달성


PostMessage (WM_SYSCOMMAND, SC_MINIMIZE); 
PostMessage (WM_SYSCOMMAND, SC_MAXIMIZE); 
PostMessage (WM_SYSCOMMAND, SC_CLOSE); 


13. 누르면 Esc를, 그리고 Enter 키를 대화 상자를 닫을 때 금지


방법 1 : 

(1), 하나의 CDialog : OnCancel 차폐 및 OnOK 과부하 : OnCancel ()와 CDialog : : OnOK (); 
(2) 다음과 같은 코드를 추가합니다 
무효 CTest6Dlg : : OnSysCommand (UINT 꾸벅꾸벅, lparam lParam) 
( 
((꾸벅꾸벅 & 0xFFF0) == IDM_ABOUTBOX 경우) 
( 
CAboutDlg dlgAbout; / /에 대한 대화 상자가 있으면 
dlgAbout.DoModal (); 
) 
다른 경우 ((꾸벅꾸벅 & 0xFFF0) == SC_CLOSE) 
( 
/ / 오른쪽 상단 모서리에있는 "X에 대한 사용자 클릭수" 
EndDialog (IDOK); 

) 
그 밖의 
( 
CDialog : : OnSysCommand (lParam) 꾸벅꾸벅; 
) 
) 

방법 2 : 

BOOL CTest6Dlg : : PreTranslateMessage (MSG) pMsg * 
( 
만약 (pMsg - "메시지가 == WM_KEYDOWN) 
( 
스위치 (pMsg - "wParam) 
( 
사건 VK_ESCAPE : 
반환이 TRUE; / / 직접 TRUE를 반환 
휴식 시간; 
사건 VK_RETURN : 
반환이 TRUE; 
휴식 시간; 
) 
) 
반환 CDialog : : PreTranslateMessage (pMsg); 
) 

방법 3 : 
Q122489 : 
기본 푸시 버튼을 해제하는 방법 취급의 MFC 대화 상자에 대한 
http://support.microsoft.com/kb/122489/en-us 


14. 대화 상자에서 키보드 및 마우스 메시지 처리


PreTranslateMessage 메시지 처리 

다음 코드 예제에서는, 당신은 WM_LBUTTONDOWN, WM_LBUTTONUP, WM_RBUTTONDOWN 등 정말 마우스 메시지를 처리할 수있는 메시지가 WM_KEYDOWN 전용 키보드를 보여줍니다. 

BOOL CTest6Dlg : : PreTranslateMessage (MSG) pMsg * 
( 
/************************************************* *********/ 
/ * 때 초점을 ComboBox에 스타일 다운 (드롭) 및 캐리지 리턴 *에 대한 응답에 대한 수정 / 
/************************************************* **********/ 
만약 (pMsg - "메시지가 == WM_KEYDOWN) 
( 
스위치 (pMsg - "wParam) 
( 
사건 VK_RETURN : 
CEdit * pEdit = (CEdit *) m_combo1.GetWindow (GW_CHILD); 
만약 (pMsg - "hwnd == pEdit -"m_hWnd) 
( 
AfxMessageBox ComboBox에의 ( "에서 편집을 누르면 입력하십시오!"); 
) 
반환이 TRUE; 
) 
) 
 
/****************************************/ 
/ * ALT WM_SYSKEYDOWN 위해 * / 
/****************************************/ 
만약 (pMsg - "메시지가 == WM_SYSKEYDOWN) 
( 
스위치 (pMsg - "wParam) 
( 
VK_F1 경우 : 
(: : GetKeyState (VK_MENU) "0) /면 / ALT + F1을 
( 
AfxMessageBox ( "")의 Alt + F1을 누르면; 
반환이 TRUE; 
) 
) 
) 
    
/****************************************/ 
/ * clistctrl에서,에서 Ctrl + * 모든 항목을 선택 / 
/****************************************/ 
만약 (pMsg - "메시지가 == WM_KEYDOWN) 
( 
만약 (pMsg - "hwnd == GetDlgItem (IDC_LIST1) -"m_hWnd) 
( 
스위치 (pMsg - "wParam) 
( 
사례 65 : / / 
(: : GetKeyState (VK_CONTROL) "0) / / 쉬프트 + 만약 입력 
( 
위해 (int 전 = 0; 난 "m_list.GetItemCount (); 난 + +) 
( 
m_list.SetItemState는 (i, LVIS_SELECTED | LVIS_FOCUSED, 
LVIS_SELECTED | LVIS_FOCUSED); 
) 
) 
반환이 TRUE; 
) 
) 
)  
 
/****************************************/ 
/ * 때 ComboBox에 초점 사용자 정의 팝업 메뉴 * 최대 / 
/****************************************/  
만약 (pMsg - "메시지가 == WM_RBUTTONDOWN) 
( 
CEdit * pEdit = (CEdit *) m_combo1.GetWindow (GW_CHILD); 
만약 (pMsg - "hwnd == pEdit -"m_hWnd) 
( 
DWORD를 dwPos = GetMessagePos (); 
포인트 CPoint (LOWORD (dwPos), HIWORD (dwPos)); 
ScreenToClient (& 포인트); 
ClientToScreen (& 포인트); 
             
CMenu 메뉴; 
(menu.LoadMenu (IDR_MENU1))를 확인; 
CMenu * 팝업 = menu.GetSubMenu (0); 
! = NULL을) (팝업 ASSERT; 
팝업 - "TrackPopupMenu (TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,이); 
) 
) 
 
반환 CDialog : : PreTranslateMessage (pMsg); 
) 


15. 대화 상자에서 숨김을 시작합니다


WM_SHOWWINDOW 메시지 매핑을 추가합니다 

무효 CTest6Dlg : : OnShowWindow (BOOL bShow, UINT nStatus) 
( 
만약 (GetStyle () & WS_VISIBLE) 
( 
CDialog : : OnShowWindow (bShow, nStatus); 
) 
그 밖의 
( 
긴 스타일 = : : GetWindowLong (*이, GWL_STYLE); 
: : SetWindowLong (*이, GWL_STYLE, 스타일 | WS_VISIBLE); 
CDialog : : OnShowWindow (SW_HIDE, nStatus); 
) 
) 


16. 대화 상자가 자동으로 화면 가장자리에 도킹


= 50 DETASTEP const int; 
BOOL AdjustPos (CWnd * pWnd, CRect * lpRect) 
( 
/ / 자동으로 부상 
int iSX = GetSystemMetrics (SM_CXFULLSCREEN); 
int ISY = GetSystemMetrics (SM_CYFULLSCREEN); 
RECT rWorkArea; 
BOOL bResult = SystemParametersInfo (SPI_GETWORKAREA, sizeof (RECT), & rWorkArea, 0); 

CRect rcWA; 
(! bResult)하는 경우 
( 
/ /를 사용하여 GetSystemMetrics의 화면 크기에 실패한 경우에는 호출 액세스 
rcWA = CRect (0,0, iSX, ISY); 
) 
그 밖의 
rcWA = rWorkArea; 

int 9 = lpRect - "왼쪽; 
int 질문답 = lpRect - "가기; 
만약 (9 "rcWA.left + DETASTEP & & 9! = rcWA.left) 
( 
/ / 왼쪽을 조정합니다 
pWnd - "SetWindowPos (NULL로, rcWA.left, 보더, 0,0, SWP_NOSIZE); 
lpRect - "OffsetRect (rcWA.left - 9, 0); 
AdjustPos (lpRect); 
반환이 TRUE; 
) 
만약 (질문답 "rcWA.top + DETASTEP & & 질문답! = rcWA.top) 
( 
/ / 조정 
pWnd - "SetWindowPos (NULL로, 9, rcWA.top, 0,0, SWP_NOSIZE); 
lpRect - "OffsetRect (0, rcWA.top - 질문답); 
AdjustPos (lpRect); 
반환이 TRUE; 
) 
만약 (9 + lpRect - "폭 ()"rcWA.right - DETASTEP & & 9! = rcWA.right - lpRect - "폭 ()) 
( 
/ / 오른쪽을 조정합니다 
pWnd - "SetWindowPos (NULL로, rcWA.right - rcW.Width (), 보더, 0,0, SWP_NOSIZE); 
lpRect - "OffsetRect (rcWA.right - lpRect -"좋아, 0); 
AdjustPos (lpRect); 
반환이 TRUE; 
) 
만약 (질문답 + lpRect - "높이 ()"rcWA.bottom - DETASTEP & & 질문답! = rcWA.bottom - lpRect - "높이 ()) 
( 
/ / 조정 
pWnd - "SetWindowPos (NULL로, 9, rcWA.bottom - rcW.Height (), 0,0, SWP_NOSIZE); 
lpRect - "OffsetRect (0, rcWA.bottom - lpRect -"하단); 
반환이 TRUE; 
) 
FALSE를 반환; 
) 

/ / 그럼 다음과 같은 ONMOVEING 이벤트 프로 시저 호출을 사용하여 
CRect r에 =* pRect; 
AdjustPos (이, & R)의; 
* pRect = (RECT) 연구; 


17. 창을 어디서나 창문에 끌어올 수있습니다 클릭

방법 1 : 
WM_LBUTTONDOWN 메시지를지도에 추가 
무효 CTest6Dlg : : OnLButtonDown (UINT nFlags, CPoint 점) 
( 
PostMessage (WM_NCLBUTTONDOWN, HTCAPTION, 0); 

CDialog : : OnLButtonDown (nFlags, 지점); 
) 

방법 2 : 
WM_NCHITTEST 메시지를지도에 추가 
참고 : ClassWizard를 있음 - "메시지 WM_NCHITTEST를 찾을 수없습니다 탭 및 클래스 정보를 필요로 선택 창에서"메시지 필터에 메시지 메시지가 나타납니다. 
무효 CTest6Dlg : : OnNCHitTest (CPoint 점) 
( 
반환 HTCAPTION; 
/ / 으 CDialog : : OnNCHitTest (지점); 
) 

아니면 참조 
http://msdn.microsoft.com/msdnmag/issues/02/12/CQA/default.aspx 


18. 달성에 초점을 전환하려면 Tab 키를 대체 키 입력을


BOOL CTest6Dlg : : PreTranslateMessage (MSG) pMsg * 
( 
만약 (pMsg - "메시지가 == WM_KEYDOWN) 
( 
만약 (pMsg - "wParam == VK_RETURN) 
pMsg - "wParam = VK_TAB; 
) 
반환 CDialog : : PreTranslateMessage (pMsg); 
) 


19. 대화 상자에서 바로 가기 키를 추가하려면


(1) CXXXApp 클래스 선언을 추가하려면 
HACCEL m_haccel; 
(2) 리소스를 볼 수 있음, 마우스 오른쪽 단추로 트리의 루트, 새로운 액셀 러레이터를 추가 삽입을 선택하면 기본 IDR_ACCELERATOR1에 대한 ID입니다. 
어떤 해당 메뉴에서 바로 가기를 추가할 수있습니다. 
(3) BOOL CXXXApp : : InitInstance에서 ()에 코드를 추가합니다 
m_haccel = LoadAccelerators (AfxGetInstanceHandle (), MAKEINTRESOURCE (IDR_ACCELERATOR1)); 
(4) CXXXApp 클래스 ProcessMessageFilter 메시지 매핑 기능을 추가 
BOOL CTest6App : : ProcessMessageFilter (int 코드 LPMSG lpMsg) 
( 
(m_haccel 경우) 
( 
만약 (: : TranslateAccelerator (m_pMainWnd - ", m_haccel,)) lpMsg m_hWnd 
반환이 TRUE; 
) 
반환 CWinApp : : ProcessMessageFilter (코드, lpMsg); 
) 

아니면 참조 
Q100770 : 
어떻게 액셀 러레이터 키 및 Visual C에서 대화 상자에서 기본 메뉴를 사용합니다 + + 
http://support.microsoft.com/kb/100770/en-us 

귀하의 응용 프로그램에 핫 키 추가 
http://msdn.microsoft.com/msdnmag/issues/1200/c/default.aspx 


20. 대화 상자를 화면에


int CX는, 사; 
HDC는 워싱턴 = : : GetDC (NULL을); 
CX는 = GetDeviceCaps (HORZRES) 직류 + GetSystemMetrics (SM_CXBORDER); 
싸이 = GetDeviceCaps (VERTRES) 직류 + GetSystemMetrics (SM_CYBORDER); 
: : ReleaseDC (0, 직류); 

/ / 제거를 캡션과 테두리 
SetWindowLong (m_hWnd, GWL_STYLE, 
GetWindowLong (m_hWnd, GWL_STYLE) & (~ (WS_CAPTION | WS_BORDER))); 

/ 위로 / 올려 창이 화면을 채우기 위해 확장 
: : SetWindowPos (m_hWnd, HWND_TOPMOST, 
- (GetSystemMetrics (SM_CXBORDER) +1), 
- (GetSystemMetrics (SM_CYBORDER) +1), 
CX는 +1, 사 +1, SWP_NOZORDER); 
아니면 참조 
http://www.codeguru.com/cpp/wd/dislog/dialog-basedapplications/article.php/c1837/ 


21. 컨트롤 대화 상자에서 최대의 최소 크기


(1) 대화 상자의 속성의 크기를 조정해야합니다 
(2) ClassWizard를 열고 - "수업 정보 탭 - 선택 창에서"메시지 필터 
(3) WM_GETMINMAXINFO 메시지를지도에 추가 
무효 CTest6Dlg : : OnGetMinMaxInfo (MINMAXINFO * lpMMI) 
( 
lpMMI - "= CPoint (200, 200) ptMinTrackSize; 
) 


22. 모덜리스 대화 상자 만들기


Q103788 : 
MFC 라이브러리와 모덜리스 대화 상자 만들기 
http://support.microsoft.com/kb/103788/EN-US/ 

참고 Visual C + +에서 MFC 샘플 
모덜리스 샘플 : 모덜리스 대화 상자로 CDialog 개체를 사용하여 
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcsample/html/_sample_mfc_MODELESS.asp 


23. 대화 상자에서 (활성화 / 비활성화, 확인 / 취소, 변경 텍스트) 메뉴 항목 상태를 변경하려면


Q242577 : 
당신은 그 명령은 사용자가 메뉴 항목의 상태를 변경할 수없습니다 인터페이스 처리기 경우 메뉴에서는 Visual C 대화 상자에 첨부되어있습니다 + + 
http://support.microsoft.com/kb/242577/en-us 


24. F1 키를 눌러 도움말에 나타납니다


Q141724 : 
컨텍스트 - CDialog 개체에 맞는 도움말 
http://support.microsoft.com/kb/141724/en-us 


MSDN의 도입에 
http://msdn2.microsoft.com/en-us/library/dyd1yfww.aspx 

아니면 당신이 F1을 화면에서 ""프롬프트 대화 상자에서 파일을 WM_HELPINFO 메시지를지도에 추가하려면 *. hlp를 찾을 수없습니다 LED를 눌러 원하는 
BOOL CTest6Dlg : : OnHelpInfo (HELPINFO * pHelpInfo) 
( 
반환이 TRUE; 
/ / 반환 CDialog : : OnHelpInfo (pHelpInfo); 문장 / / 마스크 
) 



25. 대화 상자의 입력 포커스를 설정하는 문제는 초기화됩니다

기본적으로 대화 상자를 설정하는 첫 번째 컨트롤의 탭 순서를 설정 대화 상자에 따라 편집하는 동안에 초점을 맞추고 표시를 초기화합니다. (대화 상자에서 리소스보기에서 Ctrl 키를 사용하여 탭 순서를 설정 + D를 표시 지점 설정을 위해서 마우스). 만약 당신이 인위적으로 입력 초점 초기화를 변경하려면 대화 상자의 OnInitDialog에서 TRUE를 반환 넣어 수있습니다; 반환 FALSE로 대체; 

은 MSDN의 설명은 다음과 같습니다 : 

반환 값

할지 여부를 지정 응용 프로그램을 하나의 대화 상자에서 컨트롤에 입력 포커스를 설정하고있다. OnInitDialog 반환하면 nonzero, 윈도우 대화 상자에서 첫 번째 컨트롤에 입력 포커스를 설정합니다. 응용 프로그램이있는 경우에만 그것을 명시적으로 설정하고있다 0 반환할 수있습니다 하나의 대화 상자에서 컨트롤의 입력 초점을 맞춥니다.



26. 대화 상자간에 데이터를 전달

CDlg1 : : OnButton1 () 
( 
CDlg2 dlg2; 
dlg2.m_str = _T ( "안녕하세요";) 
dlg2.m_bJudge = TRUE로; 
dlg2.DoModal (); 
) 

/ / Dlg2.h 
공개 : 
CString을 m_str; 
BOOL m_bJudge; 


/ / Dlg2.cpp 
CDlg2 : : OnInitDialog () 
( 
(m_bJudge 경우) 
GetDlgItem (IDC_EDIT1) - "SetWindowText (m_str); 
) 



27. Dlg1 오픈 dlg2 때 dlg2 dlg1 멤버 변수를 수정할 수


/ / dlg1.cpp 
# "dlg2.h"를 포함 
CDlg1 : : OnButton1 () 
( 
CDlg2 dlg2; 
dlg2.m_pDlg1 =이; 
dlg2.DoModal (); 
) 

/ / dlg2.h 
클래스 CDlg1; / / dlg1 클래스 선언에 추가 
클래스 CDlg2 : 공공 CDialog 
( 
... 
공개 : 
CDlg1 * m_pDlg1; 
) 

/ / dlg2.cpp 
# "dlg1.h"를 포함 

이 시점에서, 당신은 m_pDlg1 운영 CDlg1 클래스 멤버 변수를 통해 dlg2.cpp 수있습니다. 




28. 글꼴 대화 상자를 변경하려면 대화 상자에서 문제의 크기를 변경


Q145994 : 
어떻게 단위 대화 상자에서는 Visual C에서 현재 글꼴을 기반으로 계산합니다 + + 
http://support.microsoft.com/kb/q145994/ 

Q125681 : 
계산은 어떻게 대화 자료의 단위와 비 - 시스템 - 글꼴을 기반으로 
http://support.microsoft.com/kb/125681/en-us 




29. 시간이 때 많은 양의 데이터, 질문에 대한 응답의 인터페이스를 기다려 결과


때 프로그램에 필요한 데이터의 경우 많은 양의 검색 (예 : 디스크, 데이터 전송의 양이, 등), 이러한 계산 과정을 인터페이스 스레드 (UI가 프로세스)의 인터페이스를 스레드에 메시지 블록 울렸어요. 하기 위해서는 문제를 해결하기 위해 우리는 작업자 스레드는 계산을 처리하는 (작업자 스레드)를 만듭니다. 
여기 작업자 스레드를 만들 수있는 간단한 구현됩니다 : 
/ / xxxdlg.h 
정적 UINT MyThread (LPVOID pParam); 
CWinThread * pMyThread; 

/ / xxxdlg.cpp 
CXXXDlg : : OnButton1 () 
( 
pMyThread = AfxBeginThread (MyThread,이); 
pMyThread = NULL로; 
) 

UINT CXXXDlg : : MyThread (LPVOID pParam) 
( 
CXXXDlg = (CXXXDlg *) pParam * pDlg; 

/ / 여기에 계산 과정에 추가 

반환 0; 
) 


30. 결합 엔지니어링 리소스


하기 위해서는 대화 상자의 예제와 같이 대화 상자의 리소스로 B 조 가져다 : 

(1) *. ogx 파일을 생성 
ClassView, 오른쪽에서 열기를 B 조 프로젝트를 클릭합니다 대화 상자에서 클래스를 "갤러리에 추가"를 클릭하십시오. 
이 시점에서, "는 C : \ 프로그램 파일 \의 Microsoft Visual Studio \ 공통 \ MSDev98 \ 갤러리 \ 프로젝트 B"로 ogx 디렉토리의 파일을 생성합니다. 

(2) *. ogx 파일을 삽입 
프로젝트 메뉴에서 프로젝트를 선택하면 "프로젝트에 추가 -"구성 요소 및 컨트롤 ... 새로 삽입을 누른 다음 파일을 생성 ogx 선택을 엽니다. 
  점수 B 조 대화 상자에서 리소스에 대화 상자에서 클래스에 삽입.  . 


31. 인터넷에서, 난 그냥 볼 촉진하기 위하여 몇 가지 일반적인 기능 링크가 나와있는 많은 유용한 코드를 찾을 수있습니다


http://support.microsoft.com 
http://www.codeproject.com/dialog/ 
http://www.codeguru.com/Cpp/WD/dislog/ 


같은 시간에 컨트롤의 크기를 변경하려면 대화 상자의 크기를 변경하려면 

http://www.codeproject.com/dialog/easysize.asp 
http://www.codeproject.com/dialog/resizabledialog.asp 
http://www.vchelp.net/vchelp/archive.asp?type_id=5&class_id=1&cata_id=1&article_id=548&search_term = 
http://www.vchelp.net/vchelp/archive.asp?type_id=5&class_id=1&cata_id=1&article_id=538&search_term = 


어떻게 변수의 크기 () 압연 창문을 달성하기 위해 대화 상자 크기 조정 

Q262954 : 
방법은 Visual C 스크롤 막대와 resizeable 대화 상자를 만드는 방법 + + 
http://support.microsoft.com/default.aspx?scid=kb; 엉 - 우리; 262954 
http://www.codeproject.com/dialog/scrollablechilddialog.asp 


특정 지점이나 대화 상자의 측면에서 점점 더 큰 나타납니다 

http://www.codeproject.com/dialog/canidialog.asp 


MessageBox 클래스의 과부하 

http://www.codeproject.com/dialog/xmessagebox.asp 


옵션 설정 대화 상자 (왼쪽에서 오른쪽에 나무 하위 대화 상자)입니다 

구현 원리 : 다음 모든, 트리 할 때 항목에 해당하는 하위 대화 상자가 표시 왼쪽에 숨기기를 클릭 대화 상자의 여러 자녀 유형을 생성합니다. 

Q103375 : 
MultiDlg.exe 데모 동적 어린이 대화 상자 
http://support.microsoft.com/kb/103375/en-us 

http://www.codeproject.com/dialog/ezoptionsdlg.asp 
http://www.codeproject.com/dialog/csettingsdlg.asp 
http://www.codeguru.com/cpp/wd/dislog/optionsdialogs/article.php/c1953/ 
http://www.codeguru.com/cpp/wd/dislog/optionsdialogs/article.php/c2015/ 


달성 MSN 친구의 오른쪽 하단 구석에, 메세지 팝업 프롬프트 

http://www.codeproject.com/dialog/statusbarmsgwnd.asp 


오늘의 팁 (하루에 1) 기능을 달성하기 위해 

http://www.codeproject.com/dialog/XHTMLTipOfTheDay.asp 
http://www.codeguru.com/cpp/wd/dislog/tipoftheday/article.php/c4993/ 


불규칙 대화 

http://www.codeproject.com/dialog/SimpleIrregular.asp 


확장 및 대화 상자의 수축 

http://www.codeproject.com/dialog/dlgexpand.asp 


그라디언트 대화 상자 

http://www.codeproject.com/dialog/WinMakeInactive.asp 


화면 캡처 

http://www.codeproject.com/dialog/screencap.asp 


대화 상자에서, "가장 최근에 사용한 파일 목록"기능을 메뉴에 추가 

http://www.codeproject.com/dialog/rfldlg.asp 


닫기 대화 상자에서 점차 사라지고 

http://www.codeguru.com/cpp/wd/dislog/animation/article.php/c5063/ 


대화 상자의 배경 비트맵 

http://www.codeguru.com/cpp/wd/dislog/bitmapsimages/article.php/c1877/ 


투명 대화 상자 

http://www.codeguru.com/cpp/wd/dislog/miscellaneous/article.php/c5065/ 
http://www.codeguru.com/cpp/wd/dislog/miscellaneous/article.php/c5019/ 


대화 상자에서보기를 만들 

http://www.codeguru.com/cpp/wd/dislog/article.php/c5009/ 


스플래쉬 화면 

Q817372 : 
어떻게 대화 상자에서 스플래시 화면을 삽입하는 다른 Visual C를 사용하여 응용 프로그램을 기반 + +. NET이나 Visual C + + 2005 
http://support.microsoft.com/kb/817372/en-us 

Q815376 : 
만드는 방법과 SDI가 응용 프로그램에서 스플래시 화면을 삽입하거나 MDI를 응용 프로그램에서 Visual C + +를 사용하여. NET이나 Visual C + + 2005 
http://support.microsoft.com/kb/815376/en-us 

http://www.codeguru.com/cpp/wd/dislog/splashscreens/article.php/c2011/ 
http://www.codeguru.com/cpp/wd/dislog/miscellaneous/article.php/c5019/ 
http://www.codeguru.com/cpp/wd/dislog/splashscreens/article.php/c5029/ 


분할 대화 상자 

http://www.codeguru.com/cpp/wd/dislog/splitterwindowswithingdialogs/article.php/c4973/ 
http://www.codeguru.com/cpp/wd/dislog/splitterwindowswithingdialogs/article.php/c2031/ 
http://www.codeguru.com/cpp/wd/dislog/splitterwindowswithingdialogs/article.php/c1979/ 


타이틀 바 제목 표시줄 

http://www.codeguru.com/cpp/wd/dislog/titlebar/article.php/c1897/ 


상태 표시줄에 상태 표시줄 및 도구 모음이 도구 모음에 추가 

Q123158 : 
재단 수업 대화 상자에 컨트롤 바에 추가 
http://support.microsoft.com/kb/123158/en-us 

참고 Visual C + +에서 MFC 샘플 
DLGCBR32 샘플 : 대화 상자에 상태 표시줄 및 도구 모음 추가 데모 
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcsample/html/_sample_mfc_DLGCBR32.asp 

http://www.codeguru.com/cpp/wd/dislog/toolbarsandstatusbars/article.php/c1955/ 
http://www.codeguru.com/cpp/wd/dislog/toolbarsandstatusbars/article.php/c1939/ 
http://www.codeguru.com/cpp/wd/dislog/toolbarsandstatusbars/article.php/c1949/ 


툴팁 

Q141758 : 
어떻게 MFC는 모달 대화 상자 컨트롤에 툴팁을 추가하려면 
http://support.microsoft.com/kb/141758/en-us 

http://www.codeguru.com/cpp/wd/dislog/tooltipsfordialogcontrols/article.php/c2017/ 
http://www.codeguru.com/cpp/wd/dislog/tooltipsfordialogcontrols/article.php/c1843/ 
http://www.codeguru.com/cpp/wd/dislog/tooltipsfordialogcontrols/article.php/c1839/ 
http://www.codeproject.com/miscctrl/pptooltip.asp 



팝업 대화 상자에서 대화 상자의 가장자리를 부드럽게 

http://www.codeguru.com/cpp/wd/dislog/miscellaneous/article.php/c5061/ 

/* =-=-=-=-=-=-=-=-=-=-=-=-=-= Window Messages =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

#define WM_NULL           0x0000
#define WM_CREATE                   0x0001
#define WM_DESTROY                  0x0002
#define WM_MOVE                     0x0003
#define WM_SIZE                     0x0005
#define WM_ACTIVATE                 0x0006

/* WM_ACTIVATE state values */
#define     WA_INACTIVE             0
#define     WA_ACTIVE               1
#define     WA_CLICKACTIVE          2

#define WM_SETFOCUS                 0x0007
#define WM_KILLFOCUS                0x0008
#define WM_ENABLE                   0x000A
#define WM_SETREDRAW                0x000B
#define WM_SETTEXT                  0x000C
#define WM_GETTEXT                  0x000D
#define WM_GETTEXTLENGTH            0x000E
#define WM_PAINT                    0x000F
#define WM_CLOSE                    0x0010
#define WM_QUERYENDSESSION         0x0011
#define WM_QUIT                     0x0012
#define WM_QUERYOPEN                0x0013
#define WM_ERASEBKGND               0x0014
#define WM_SYSCOLORCHANGE          0x0015
#define WM_ENDSESSION               0x0016
#define WM_SHOWWINDOW               0x0018
#define WM_WININICHANGE             0x001A
#if(WINVER >= 0x0400)
#define WM_SETTINGCHANGE        WM_WININICHANGE
#endif /* WINVER >= 0x0400 */

#define WM_DEVMODECHANGE          0x001B
#define WM_ACTIVATEAPP              0x001C
#define WM_FONTCHANGE               0x001D
#define WM_TIMECHANGE               0x001E
#define WM_CANCELMODE               0x001F
#define WM_SETCURSOR                0x0020
#define WM_MOUSEACTIVATE           0x0021
#define WM_CHILDACTIVATE            0x0022
#define WM_QUEUESYNC                0x0023

#define WM_GETMINMAXINFO            0x0024
// end_r_winuser

// begin_r_winuser
#define WM_PAINTICON             0x0026
#define WM_ICONERASEBKGND      0x0027
#define WM_NEXTDLGCTL               0x0028
#define WM_SPOOLERSTATUS           0x002A
#define WM_DRAWITEM                 0x002B
#define WM_MEASUREITEM              0x002C
#define WM_DELETEITEM               0x002D
#define WM_VKEYTOITEM               0x002E
#define WM_CHARTOITEM               0x002F
#define WM_SETFONT                  0x0030
#define WM_GETFONT                  0x0031
#define WM_SETHOTKEY                0x0032
#define WM_GETHOTKEY                0x0033
#define WM_QUERYDRAGICON            0x0037
#define WM_COMPAREITEM              0x0039
#if(WINVER >= 0x0500)
#define WM_GETOBJECT             0x003D
#endif /* WINVER >= 0x0500 */
#define WM_COMPACTING            0x0041
#define WM_COMMNOTIFY             0x0044  /* no longer suported */
#define WM_WINDOWPOSCHANGING   0x0046
#define WM_WINDOWPOSCHANGED    0x0047

#define WM_POWER                 0x0048
/*
* wParam for WM_POWER window message and DRV_POWER driver notification
*/
#define PWR_OK                   1
#define PWR_FAIL                 (-1)
#define PWR_SUSPENDREQUEST      1
#define PWR_SUSPENDRESUME       2
#define PWR_CRITICALRESUME       3

#define WM_COPYDATA              0x004A
#define WM_CANCELJOURNAL         0x004B
// end_r_winuser

// begin_r_winuser
#if(WINVER >= 0x0400)
#define WM_NOTIFY                0x004E
#define WM_INPUTLANGCHANGEREQUEST  0x0050
#define WM_INPUTLANGCHANGE      0x0051
#define WM_TCARD                    0x0052
#define WM_HELP                     0x0053
#define WM_USERCHANGED            0x0054
#define WM_NOTIFYFORMAT           0x0055

#define NFR_ANSI                    1
#define NFR_UNICODE                 2
#define NF_QUERY                    3
#define NF_REQUERY                  4

#define WM_CONTEXTMENU              0x007B
#define WM_STYLECHANGING            0x007C
#define WM_STYLECHANGED             0x007D
#define WM_DISPLAYCHANGE            0x007E
#define WM_GETICON                  0x007F
#define WM_SETICON                  0x0080
#endif /* WINVER >= 0x0400 */

#define WM_NCCREATE                 0x0081
#define WM_NCDESTROY               0x0082
#define WM_NCCALCSIZE              0x0083
#define WM_NCHITTEST                0x0084
#define WM_NCPAINT                  0x0085
#define WM_NCACTIVATE              0x0086
#define WM_GETDLGCODE             0x0087
#define WM_SYNCPAINT                0x0088
#define WM_NCMOUSEMOVE          0x00A0
#define WM_NCLBUTTONDOWN       0x00A1
#define WM_NCLBUTTONUP           0x00A2
#define WM_NCLBUTTONDBLCLK          0x00A3
#define WM_NCRBUTTONDOWN            0x00A4
#define WM_NCRBUTTONUP              0x00A5
#define WM_NCRBUTTONDBLCLK    0x00A6
#define WM_NCMBUTTONDOWN      0x00A7
#define WM_NCMBUTTONUP          0x00A8
#define WM_NCMBUTTONDBLCLK    0x00A9

#define WM_KEYFIRST                0x0100
#define WM_KEYDOWN                  0x0100
#define WM_KEYUP                    0x0101
#define WM_CHAR                     0x0102
#define WM_DEADCHAR                 0x0103
#define WM_SYSKEYDOWN              0x0104
#define WM_SYSKEYUP                 0x0105
#define WM_SYSCHAR                  0x0106
#define WM_SYSDEADCHAR             0x0107
#define WM_KEYLAST                  0x0108

#if(WINVER >= 0x0400)
#define WM_IME_STARTCOMPOSITION  0x010D
#define WM_IME_ENDCOMPOSITION      0x010E
#define WM_IME_COMPOSITION          0x010F
#define WM_IME_KEYLAST              0x010F
#endif /* WINVER >= 0x0400 */

#define WM_INITDIALOG               0x0110
#define WM_COMMAND                  0x0111
#define WM_SYSCOMMAND              0x0112
#define WM_TIMER                    0x0113
#define WM_HSCROLL                  0x0114
#define WM_VSCROLL                  0x0115
#define WM_INITMENU                 0x0116
#define WM_INITMENUPOPUP            0x0117
#define WM_MENUSELECT               0x011F
#define WM_MENUCHAR                 0x0120
#define WM_ENTERIDLE                0x0121
#if(WINVER >= 0x0500)
#define WM_MENURBUTTONUP          0x0122
#define WM_MENUDRAG                 0x0123
#define WM_MENUGETOBJECT          0x0124
#define WM_UNINITMENUPOPUP        0x0125
#define WM_MENUCOMMAND            0x0126
#endif /* WINVER >= 0x0500 */

#define WM_CTLCOLORMSGBOX        0x0132
#define WM_CTLCOLOREDIT             0x0133
#define WM_CTLCOLORLISTBOX        0x0134
#define WM_CTLCOLORBTN              0x0135
#define WM_CTLCOLORDLG              0x0136
#define WM_CTLCOLORSCROLLBAR    0x0137
#define WM_CTLCOLORSTATIC          0x0138

#define WM_MOUSEFIRST               0x0200
#define WM_MOUSEMOVE                0x0200
#define WM_LBUTTONDOWN              0x0201
#define WM_LBUTTONUP                0x0202
#define WM_LBUTTONDBLCLK            0x0203
#define WM_RBUTTONDOWN              0x0204
#define WM_RBUTTONUP                0x0205
#define WM_RBUTTONDBLCLK            0x0206
#define WM_MBUTTONDOWN              0x0207
#define WM_MBUTTONUP                0x0208
#define WM_MBUTTONDBLCLK            0x0209

#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
#define WM_MOUSEWHEEL              0x020A
#define WM_MOUSELAST                0x020A
#else
#define WM_MOUSELAST                0x0209
#endif /* if (_WIN32_WINNT < 0x0400) */

#if(_WIN32_WINNT >= 0x0400)
#define WHEEL_DELTA              120     /* Value for rolling one detent */
#endif /* _WIN32_WINNT >= 0x0400 */
#if(_WIN32_WINNT >= 0x0400)
#define WHEEL_PAGESCROLL            (UINT_MAX) /* Scroll one page */
#endif /* _WIN32_WINNT >= 0x0400 */

#define WM_PARENTNOTIFY          0x0210
#define WM_ENTERMENULOOP         0x0211
#define WM_EXITMENULOOP          0x0212

#if(WINVER >= 0x0400)
#define WM_NEXTMENU              0x0213
// end_r_winuser

MFC에서 다이얼로그를 띄운뒤에 VCL에서 하듯이..
if(AAA)
{
    delete AAA;
    AAA = NULL;
}
로 처리하면 다음과 같은 경고 메시지가 발생한다..

Warning: calling DestroyWindow in CDialog::~CDialog --
 OnDestroy or PostNcDestroy in derived class will not be called.

이럴때는 한가지 작업을 더해주어야만 한다..

정상 종료 시키고 메모리에서 없애주도록 하자...
 if(AAA != NULL)
{
    (AAA)->DestroyWindow();
    delete (AAA); 
    (AAA) = NULL;
}

[원문] http://support.microsoft.com/kb/158552/en-us/
          http://support.microsoft.com/kb/158552/ko

CPropertySheet::DoModal() 또는 CPropertySheet::Create() 호출하면 예외가 발생할 수 있습니다.
현상
CPropertySheet::DoModal()
또는 CPropertySheet::Create() 호출하면 예외가 발생할 수 있습니다.
출력 창에 다음 메시지가 표시됩니다.
<program.exe> (Comctl32.dll) 에서 첫 번째 예외가: 0xC0000005: 액세스 위반.
예상되는 예외와 운영 체제에 의해 처리됩니다. 이 경우에만 이러한 방법 중 하나를 호출하면 처음 발생하여 호출에서는 이 첫 번째 예외가 생성되지 않습니다.

원인
CommCtl32.dll 해당 페이지에 대한 리소스를 수정하는 시도합니다. 읽기 전용 섹션에 리소스가 일반적으로 때문에 운영 체제에서 발견되었습니다 첫 번째 기회가 예외를 throw합니다. 운영 체제에서 이 예외를 처리하는 및 리소스를 쓸 수 있도록 모든 다음 정상적으로 완료됩니다. 이 첫 번째 예외가 않고 모든 후속 호출을 완료하려면 리소스를 쓰기 이제 때문에

해결방법
첫 번째 예외가 안전하게 운영 체제에 의해 처리되기 때문에 무시해도 됩니다.

예외를 방지하려면 다음 방법 중 하나를 사용하십시오.
  • 방법 1 : 읽기/쓰기 리소스를 만들기. 다음과 같이 설정을 링커 추가하여 이렇게 할 수 있습니다:
    /SECTION:.rsrc,rw
  • 방법 2 : MS Sans 않습니다 페이지의 글꼴 변경. MFC는 페이지의 대화 템플릿 글꼴을 확인합니다. MS Sans 않으면 MFC 읽기/쓰기 메모리 리소스 복사본을 만들어 및 다음 글꼴을 수정하고 C mCtl32.dll 전달합니다. DLL 페이지 서식 파일에 쓸 때 메모리 읽기 쓰기 기록합니다. Therfore, 예외가 throw될 수 없습니다.
  • 방법 3 : try/catch(...) 블록을 속성 시트를 만드는 호출이 없는 함. 대신, catch 블록에 특정 예외 catch 합니다.
속성 시트를 서버의 OLE 자동화 서버의 메서드를 통해 호출한 일부이면, 읽기/쓰기 OLE 예외를 catch 때문에 처음 두 방법 중 하나를 사용하여 리소스를 확인하십시오.

참고 읽기/쓰기 리소스를 변경할 때 리소스는 페이지 파일에 쓸 수 있습니다.

현재상태
이 동작은 의도적으로입니다.

예제
   /* Compile options needed: default
   */

   /***** this code will cause unpredictable results *****/
   try
   {
       sheet.DoModal();
   }
   catch(...)
   {
   }

   /***** this code is OK *****/
   try
   {
       if (0 == sheet.DoModal())
           throw "DoModal() failed!";
   }
   catch(char * str)
   {
       TRACE ("Exception thrown: %s\n", str);
   }
 
참조
자세한, Microsoft 기술 자료에 있는 문서를 보려면 다음 문서 번호를 클릭하십시오.
126630  (http://support.microsoft.com/kb/126630/ ) 읽기 전용 리소스 섹션이 있습니다.


본 문서의 정보는 다음의 제품에 적용됩니다.
  • Microsoft Foundation Class Library 4.2 을(를) 다음과 함께 사용했을 때
    • Microsoft Visual C++ 4.0 Standard Edition
    • Microsoft Visual C++ 4.1 Subscription
    • Microsoft Visual C++ 4.2 Enterprise Edition
    • Microsoft Visual C++ 4.2 Professional Edition
    • Microsoft Visual C++ 5.0 Enterprise Edition
    • Microsoft Visual C++ 5.0 Professional Edition
    • Microsoft Visual C++ 6.0 Enterprise Edition
    • Microsoft Visual C++ 6.0 Professional Edition
    • Microsoft Visual C++, 32-bit Learning Edition 6.0
    • Microsoft Visual C++ .NET 2002 Standard Edition
    • Microsoft Visual C++ .NET 2003 Standard Edition

쓰레드 동기화 오브젝트

 (Thread Synchronization Objects)

 쓰레드가 2개 이상 실행될 때 여러 가지 변수가 있습니다.

하나의 공유자원(예를 들어 동시에 접근하는 변수) 에 접근할 때, 파일 입출력 이나 디바이스I/O작업을 할 때 동기화 오브젝트가 필요합니다.

동기화 오브젝트 없이 쓰레드가 공유 자원을 사용할 때 공유자원이 원치 않은 값이 될수 있고, I/O작업 시 쓰레드가 I/O작업이 끝날 때 까지 무한정 블로킹(blocking : 특정 함수가 리턴 될 때 까지 기다림)현상이 발생할 수 있습니다.

동기화 오브젝트를 사용하여 다중 쓰레드에서 어떻게 안전 하게 공유자원에 접근하고 다른 쓰레드간의 실행 순서등을 조작하는지에 대해 알아 보겠습니다.

동기화 오브젝트는 유저 모드와 커널 모드로 분류할 수 있습니다.

  유저 모드

 유저 모드는 현재 프로세스/쓰레드 내의 상태를 말합니다.

유저모드에서는 커널 오브젝트(프로세스, 파일, 디바이스 등)으로 바로 접근을 할 수 없고, 커널 오브젝트로 접근 시 시스템에 의해 변환 작업이 이루어집니다.

이런 변환 작업은 시간을 많이 걸리는 작업이기 때문에 유저 모드가 커널 모드 보다 속도가 빠릅니다.

유저 모드 동기화 방법은 코드레벨에서 동기화 하는 방법을 이야기 합니다.

유저모드에서 동기화는 사용하기 쉽고 커널 모드 동기화 함수들에 비해 속도가 빠른 장점이 있지만 커널 오브젝트(파일 I/O, 프로세스, 쓰레드 등)의 동기화는 불가능하다는 단점이 있습니다.

 Interlocked

 Interlocked 함수들은 다중 쓰레드에서 공유변수들을 안전하게 1씩 증가/감소, 특정값을 증가 , 비트 연산을 할 수 있습니다.

Intlocked 함수는 사용하기 쉬우므로 길게 설명은 하지 않겠습니다.

아래 사이트를 참조하시길 바랍니다.

http://msdn2.microsoft.com/en-us/library/ms686360(VS.85).aspx

 

 크리티컬 섹션(CRITICAL SECTION)

 크리티컬 섹션은 특정 코드영역을 쓰레드가 동시에 실행되는 것을 막아 줍니다.

아래는 크리티컬 섹션 관련 함수들입니다.

 

DeleteCriticalSection

크리티컬 섹션 오브젝트를 삭제 합니다.

InitializeCriticalSection

크리티컬 섹션 오브젝트를 초기화 합니다.

InitializeCriticalSectionAndSpinCount

크리티컬 섹션 오브젝트를 초기화 하고 스핀 카운트를 설정합니다.

InitializeCriticalSectionEx

크리티컬 섹션을 초기화하고 스핀카운트 설정, 부가기능을 설정합니다.

LeaveCriticalSection

크리티컬 섹션 오브젝트 권한을 해제합니다..

SetCriticalSectionSpinCount

특정 크리티컬 섹션 오브젝트 스핀카운트를 설정합니다.

TryEnterCriticalSection

블로킹(Wait) 되지 않고 크리티컬 섹션 오브젝트의 권한을 요청합니다.


InitializeCriticalSectionAndSpinCount 함수는 스핀 카운트를 두어서 쓰레드가 크리티컬 섹션 오브젝트를 획득하지 못하면 Wait상태로 일정 시간(스핀카운트) 루프를 돌아 크리티컬 섹션오브젝트가 해제 되었는지 체크합니다.

해제되지 않았으면 Sleep하게 됩니다.

이 함수는 멀티 프로세서 환경에서만 유효하며, 스핀카운터는 4000을 추천(Windows Via C/C++)하지만 자신의 환경에서 값을 바꾸어 가며 테스트 해보길 권장합니다.

         

 #include <Windows.h>

CRITICAL_SECTION g_cs;

 //크리티컬 섹션 오브젝트를 초기화 합니다.

void InitCriticalSection()

{

        InitializeCriticalSection(&g_cs);

}

 

unsigned _stdcall CallThreadHandlerProc(void *pThreadHandler)

{

        while (bExit == FALSE)

        {

               if(TryEnterCriticalSection(&g_cs))

               {

                       //쓰레드 작업을 수행 합니다.

                       //수행 하고 LeaveCriticalSection 함수를 호출

                       //하여 크리티컬 섹션 오브젝트를 해제합니다.

 

                       LeaveCriticalSection(&g_cs);

               }

               else

               {

                        // 크리티컬 섹션 오브젝트 획득에 실패 시 수행할

                        // 작업을 선언합니다.

                        // SwitchToThread함수를 호출하여 다른 쓰레드로

                        // 스위칭 합니다.

                       SwitchToThread();                    

               }             

        }

        DWORD exitCode;

        GetExitCodeThread(InputThrd, &exitCode);

        _endthreadex(exitCode);

        return 0;

}


**Sleep() 함수와 SwitchToThread()함수는 디스패쳐가 다른 쓰레드로 스케쥴 하도록 합니다.

차이점은 Sleep()함수는 현재 쓰레드보다 우선순위가 같거나 높은 쓰레드가 없으면 쓰레드 전체를 리스케쥴링(rescheduling)합니다.

 

Slim Reader/Writer Locks

 Slim reader/writer (SRW) locks 하나의 프로세스내의 쓰레드들이 공유자원을 동기화 할 수 있습니다.

아주 작은 메모리를 차지하면서 속도도 빠릅니다.

Reader 쓰레드는 공유자원을 읽고 Writer 쓰레드는 공유자원에 쓰기 작업을 할수 있습니다.

다중 쓰레드가 공유자원을 읽고 쓰기를 , 크리티컬 섹션과 뮤텍스 같은 상호배제 오브젝트(exclusive locks)들은 reader 쓰레드는 계속 돌고 writer 쓰레드는 거의 돌지 못하면 병목현상(bottle neck) 발생 있습니다.

SRW locks 공유자원에 접근 할 수 있는 두 가지 모드를 제공합니다.

·Shared mode : 읽는 작업을 하는 쓰레드가 여러 개일 때 공유자원을 읽기 전용으로 접근할 수 있도록 해서 동시 다발적으로 작업을 할 수 있도록 합니다.  만약 읽는 작업이 쓰는 작업을 초과 할 경우, 성능과 처리량은 크리티컬 섹션과 동일하게 됩니다.
·Exclusive mode : 읽기/쓰기 쓰레드는 하나의 쓰레드만 접근 할 수 있습니다.  Exclusive mode로 락이 걸려지면 다른 쓰레드들은 공유자원에 접근할 수 없습니다.

하나의 SRW lock 두 가지 모드를 동시에 가질 수 있습니다. 읽는 쓰레드는 Shared mode 쓰는 쓰레드는 Exclusive mode 작업을 있습니다.  어떤 쓰레드가 소유권을 먼저 가질지는 알수 없습니다. SRW Locks 공정하거나 선입선출(First In First Out : FIFO)방식이 아닙니다.

SRW lock 포인터 크기를 가집니다. 장점은 속도가 빠르고 lock상태의 변환이 빠르다는 입니다.

단점은 아주 작은 상태 정보만 저장이 되어 재귀적으로 SRW locks 가질 없습니다. Shared Mode 쓰레드가 Shred Mode 변환 될수 없습니다.

SWR Locks Windows Server 2008,Vista 에서만 사용이 가능합니다.

아래는 SRW lock 함수들 입니다.

SRW lock function

Description

AcquireSRWLockExclusive

SRW lock  exclusive mode 얻습니다.

AcquireSRWLockShared

SRW lock shared mode 얻습니다.

InitializeSRWLock

SRW lock 초기화 합니다.

ReleaseSRWLockExclusive

exclusive mode SRW lock 해제 합니다.

ReleaseSRWLockShared

shared mode SRW lock 해제 합니다.

SleepConditionVariableSRW

SRW작업이 완료 될때까지 Sleep 합니다.

 커널 모드

유저 모드에서 커널 오브젝트에 접근을 할 때 시스템은 커널 모드로 변환을 합니다.

커널 오브젝트에는 File, Event, Mutex, Semaphore, Process, Waitable Timer, Job, Thread 가 있습니다.

커널 모드에서 동기화는 커널 오브젝트가 non-Signal인지 Signal 상태인지를 보고 쓰레드를 스케쥴링합니다.

커널 오브젝트가 signal상태이면 쓰레드가 돌아갈 준비가 된 상태이고, non-signal 상태이면 쓰레드는 기다림(Wait)상태 입니다.

 

이벤트(EVENT)
 가장 많이 보편화되고 많이 쓰는 다중 쓰레드 동기화 오브젝트가 이벤트가 아닌가 생각이 됩니다.

이벤트로 다중 쓰레드 동기화 하는 방법에는 두 가지 방법이 있습니다.

개발자가 직접 이벤트를 수동으로 signal/non-signal 상태로 변환 하는 것과 시스템이 자동으로 이벤트를 signal/non-signal상태로 변환 하는 방법입니다.

이벤트를 기다리는 방법은 WaitForSingleObjec/WaitForSingleObject 함수를 사용합니다. 이벤트가 non-signal상태가 될 때까지 쓰레드는 Wait상태로 됩니다.

이벤트 및 모든 커널 오브젝트는 사용이 끝나면 CloseHandle로 사용을 종료 해야 합니다.

 

Event function

Description





CreateEvent

이벤트 오브젝트를 생성하거나 오픈 합니다.





CreateEventEx

이벤트 오브젝트를 생성하거나 오픈 합니다.(접근 권한을 줄수 있습니다.)





OpenEvent

존재하는 이름이 있는 이벤트 오브젝트를 오픈 합니다.





PulseEvent

특정 이벤트 오브젝트를 signal 상태로 바꾸고 일정시간 non-signal상태로 바끕니다.





ResetEvent

이벤트 오브젝트를 non-signal 상태로 놓습니다.        





SetEvent

이벤트 오브젝트를 signal 상태로 놓습니다.          






 
간단 하게 SDI 프로그램에서 수동 모드(passive mode) 이벤트를 이용하여 사각형과 원을 그리는 멀트 쓰레드 프로그램을 보겠습니다.

 BOOL CEventSampleView::PreCreateWindow(CREATESTRUCT& cs)

{

        // TODO: CREATESTRUCT cs를 수정하여 여기에서

        //  Window 클래스 또는 스타일을 수정합니다.

        srand( (unsigned)time( NULL ) );

 

        //종료조건을 초기화합니다.

        m_bContinue = TRUE;

        //수동모드 이벤트 오브젝트를 생성합니다.

        m_DrawEvent = CreateEvent(0, TRUE, TRUE, _T("DrawEvent"));

 

        // 시그널 상태로 둡니다.

        SetEvent(m_DrawEvent);

       

        return CView::PreCreateWindow(cs);

}

 

/*OnDraw 메시지 핸들러에서 사각형을 그리는 쓰레드와

원을 그리는 쓰레드를 생성합니다.*/

void CEventSampleView::OnDraw(CDC* /*pDC*/)

{

        CEventSampleDoc* pDoc = GetDocument();

        ASSERT_VALID(pDoc);

        if (!pDoc)

               return;

        m_RectThrd = AfxBeginThread(RectThreadProc,reinterpret_cast<LPVOID>(this));

        m_CricleThrd = AfxBeginThread(CircleThreadProc, reinterpret_cast<LPVOID>(this));

        // TODO: 여기에 원시 데이터에 대한 그리기 코드를 추가합니다.

}

 

/*사각형을 그리는 쓰레드 프로시저*/

UINT CEventSampleView::RectThreadProc(__in LPVOID lpParameter)

{

        CEventSampleView* pView = reinterpret_cast<CEventSampleView*>(lpParameter);

        int x=0,y=0, cx=0, cy=0;

        cx = 100;

        cy = 100;

        while(pView->m_bContinue)

        {

               //시그널상태가 될 때까지 기다립니다.

               WaitForSingleObject(pView->m_DrawEvent, INFINITE);

               //이벤트 오브젝트를 받아오면 넌시그널 상태로 둡니다.

               ResetEvent(pView->m_DrawEvent);

              

               HDC hDC = ::GetDC(pView->GetSafeHwnd());

               x= rand()%300;

               y = rand()%300;

               ::Rectangle(hDC,x, y, x+cx, y+cy);

               ::ReleaseDC(pView->GetSafeHwnd(),hDC);

               // 작업이 끝나면 이벤트를 시그널상태로 두어 다음 쓰레드가 가질 수

               // 있도록 합니다.

               SetEvent(pView->m_DrawEvent);

        }

        DWORD dCode=0;

        GetExitCodeThread(pView->m_CricleThrd->m_hThread, &dCode);

        AfxEndThread(dCode, TRUE);

        return 0;

}

/*원을 그리는 쓰레드 프로시저*/

UINT CEventSampleView::CircleThreadProc(__in LPVOID lpParameter)

{

        CEventSampleView* pView = reinterpret_cast<CEventSampleView*>(lpParameter);

        int x=0,y=0, cx=0, cy=0;

        cx = 100;

        cy = 100;

        while(pView->m_bContinue)

        {

               WaitForSingleObject(pView->m_DrawEvent, INFINITE);

               ResetEvent(pView->m_DrawEvent);

               HDC hDC = ::GetDC(pView->GetSafeHwnd());

               x= rand()%300;

               y = rand()%300;

               ::Ellipse(hDC,x, y, x+cx, y+cy);

               ::ReleaseDC(pView->GetSafeHwnd(),hDC);

               SetEvent(pView->m_DrawEvent);

        }

        DWORD dCode=0;

        GetExitCodeThread(pView->m_CricleThrd->m_hThread, &dCode);

        AfxEndThread(dCode, TRUE);

        return 0;

}

//프로그램이 종료할 때 종료조건을 맞춰 주고 쓰레드 종료 메시지를 주어 정상적으로

//종료하도록 하고, 이벤트 핸들을 닫습니다.

void CEventSampleView::OnDestroy()

{

        CView::OnDestroy();

        m_bContinue = FALSE;

        DWORD dExitCode = 0;

        GetExitCodeThread(m_CricleThrd->m_hThread,&dExitCode);

        PostQuitMessage(dExitCode);

 

        GetExitCodeThread(m_RectThrd->m_hThread,&dExitCode);

        PostQuitMessage(dExitCode);

 

        CloseHandle(m_DrawEvent);

}


 
뮤텍스(MUTEX)

뮤텍스는 하나의 공유자원에 대한 상호 배타(mutual exclusive)적으로 동기화 하는 방법입니다.  뮤텍스는 서로 다른 프로세스의 쓰레드의 동기화를 할수 있습니다.  이 특성을 이용해서 보통 하나 이상의 프로그램을 실행하기 위해 뮤텍스를 이용합니다.(이걸 깨는 방법도 있죠.)

뮤텍스는 다음과 같은 규칙이 있습니다.

Ø  쓰레드의 ID 0(유효하지 않은 쓰레드 ID)이면 뮤텍스의 소유권은 어느 쓰레드에게도 없다는 의미 이고 뮤텍스 오브젝트는 시그널된 상태입니다.

Ø  쓰레드 ID 0이 아닌 값이면, 해당쓰레드(생성 시킨 쓰레드)가 소유권을 가지면 뮤텍스 오브젝트는 non-signal상태 입니다.

Ø  다른 커널 오브젝트와는 달리 뮤텍스는 소유권(thread ownership)이라는 개념이 있습니다. 

뮤텍스를 해제할 때(ReleaseMutex), 쓰레드 ID와 생성할 때 설정한 쓰레드의 ID가 맞지 않으면 해제에 실패하고 시스템은 해당 뮤텍스의 시그널 상태를 기다리는 다른 쓰레드를 스케쥴링 합니다.

뮤텍스의 소유권을 가진 쓰레드가 뮤텍스를 해제 하지 않고 종료 되면, 시스템은 해당 뮤텍스를 “abandoned”상태로 두고, 이 뮤텍스를 기다리는 쓰레드를 찾아 기다리고 있는 쓰레드에 뮤텍스의 소유권을 주고 해당 쓰레드를 스케쥴링 합니다.

 

Mutex function

Description

CreateMutex

뮤텍스 오브젝트를 생성하거나 오픈 합니다.

CreateMutexEx

뮤텍스 오브젝트를 생성하거나 오픈합니다. 접근 권한 속성을 있습니다.

OpenMutex

이름이 있는 뮤텍스 오브젝트를 오픈 합니다.

ReleaseMutex

뮤텍스 오브젝트를 해제합니다.

 http://msdn2.microsoft.com/en-us/library/ms686927(VS.85).aspx

 
세마포어(SEMAPHORE)

 세마포어는 공유 자원의 카운팅의 용도로 사용합니다.

세마포어는 사용 개수(usage count)이외에 signed 32비트 값 2개를 더 가지고 있습니다.

Ø  최대 리소스 카운트(maximum resource count) : 세마포어가 관리할 수 있는 최대 리소스의 개수.

Ø  현재 리소스 카운트(current resource count) : 현재 사용 가능한 리소스의 개수.

세마포어는 다음과 같은 규칙을 가지고 동작을 합니다.

Ø  현재 리소스 카운터가 0보다 크면(>0) 세마포어 오브젝트는 signal 상태입니다.

Ø  현재 리소스 카운터가 0이면, 세마포어 오브젝트는 non-signal상태입니다. 

Ø  시스템은 현재 리소스카운터를 값이 되지 않도록 합니다.

Ø  현재 리소스 카운터는 최대 리소스 카운터 보다 클 수 없습니다.

 

Semaphore function

Description

CreateSemaphore

세마포어를 생성/오픈 합니다.

CreateSemaphoreEx

세마포어를 생성/오픈 합니다. 접근 권한을 있습니다.

OpenSemaphore

이름이 있는 세마포어 오브젝트를 오픈합니다.

ReleaseSemaphore

사용 가능한 리소스 개수를 증가 시킵니다..

 세마포어 사용 예는 아래 사이트를 참조 하세요.

http://msdn2.microsoft.com/en-us/library/ms686946(VS.85).aspx


Waitable Timer

Waitable Timer 오브젝트는 특정 시간이 되면 오브젝트가 시드널 됩니다.

특정 시간 마다 어떤 동작을 해야 할 때 사용할 수 있습니다.

Waitable-timer function

Description

CancelWaitableTimer

Waitable Timer 오브젝트를 비활성화 시킵니다.

CreateWaitableTimer

Waitable Timer 생성하거나 오픈 합니다.

CreateWaitableTimerEx

Waitable Timer 생성/오픈 합니다.

OpenWaitableTimer

이름이 붙여진 Waitable Timer 오브젝트를 오픈 합니다.

SetWaitableTimer

Waitable Timer 오브젝트를 활성화 시키거나, Waitable Timer 오브젝트가 시그널 되었을 완료 통보 프로시져를 등록 있습니다..

TimerAPCProc

SetWaitableTimer 함수로 등로한 완료 통보 프로시져 선언.

 

Timer-queue Timer

 Timer queue Timer 오브젝트는 일정시간이 지나면 시그널 되는 동작은 Waitable Timer 와 같습니다.

Timer Queue Timer 오브젝트는 일정 시간이 지나면 시그널 되는 오브젝트이고, Timer Queue오브젝트가 Timer Queue Timer 오브젝트를 큐 형태로 관리하면서

해당 프로시저를 호출 합니다.

 

위의 그림은 Timer Queue오브젝트가 Timer Queue Timer 오브젝트를 관리하고,

Timer Queue Timer가 시그널 되면 해당 프로시저를 호출하는 모습입니다.


Timer-queue timer function

Description

ChangeTimerQueueTimer

Timer queue timer 오브젝트의 속성을 변경 합니다..

CreateTimerQueue

Timer Queue 오브젝트를 생성합니다.

CreateTimerQueueTimer

Timer Queue Timer 오브젝트를 생성합니다.

DeleteTimerQueue

타이머 오브젝트를 삭제 합니다.

DeleteTimerQueueEx

타이머 오브젝트를 삭제 합니다.

DeleteTimerQueueTimer

Timer Queue 있는 Timer Queue Timer 오브젝트를 삭제 합니다.

 

쓰레드간 통신

  마지막으로 쓰레드간 통신 하는 방법을 알아 보겠습니다.

윈도우 프로그래밍을 하면 윈도우에 SendMessage/PostMessage 함수로 메시지를 보내 듯이 쓰레드에 메시지를 보내고 받으면서 쓰레드간 통신을 할 수 있습니다.

쓰레드에 메시지를 보내는 함수는 PostThreadMessage 입니다.

BOOL PostThreadMessage(      
    DWORD idThread,  
/*해당 쓰레드 ID*/

    UINT Msg,       /*메시지 ID*/

    WPARAM wParam,    /*메시지를 받는 쓰레드로 넘겨주는 WPARAM 인자*/

    LPARAM lParam     /* 메시지를 받는 쓰레드로 넘겨주는 LPARAM 인자*/

);

 
PostThread
로 보낸 메시지는 쓰레드 프로시저에서 PeekMessage/GetMessage로 받을 수 있습니다.

http://msdn2.microsoft.com/en-us/library/ms644936(VS.85).aspx

BOOL GetMessage(      
    LPMSG lpMsg,          
//MSG 구조체의 포인터 타입

    HWND hWnd,             //윈도우 핸들

    UINT wMsgFilterMin,    //필터링할 최소 메시지 ID

    UINT wMsgFilterMax     //필터링할 최대 메시지 ID

);

 

http://msdn2.microsoft.com/en-us/library/ms644943.aspx

 

BOOL PeekMessage(      
    LPMSG lpMsg,          
//MSG 구조체의 포인터 타입

    HWND hWnd,             //윈도우 핸들

    UINT wMsgFilterMin,    //필터링할 최소 메시지 ID

    UINT wMsgFilterMax,    //필터링할 최대 메시지 ID

    UINT wRemoveMsg        //메시지 큐에 해당 메시지를 지울지 안지울지 설정

);

 
PeekMessage
GetMessage의 차이점은, GetMessage는 메시지가 메시지 큐에 들어 올 때가지 블록 되고 Peek메시지는 메시지가 없으면 FALSE를 리턴 합니다.

더 자세한 사항은 차고 사이트를 참고 하세요.

 아래 예제 코드는 쓰레드 프로시져에서 메시지를 확인하고, 다른 작업을 수행 하는 예제 코드입니다.

 unsigned _stdcall CallThreadHandlerProc(void *pThreadHandler)

{

        while (bExit == FALSE)

        {

               MSG msg;

             BOOL res = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);

             if (res)

             {

                        //0x404메세지 가 들어오면 특정 작업 수행

                    if (msg.message = 0x404)

                    {                  

                           std::cout<<"Message Received"<<std::endl;

                    }

             }

 

               //다른 작업 수행

        }

        DWORD exitCode;

        GetExitCodeThread(InputThrd, &exitCode);

        _endthreadex(exitCode);

        return 0;

}

………………………………………….

//다른 쓰레드에서 쓰레드에 메시지를 보냅니다.

BOOL res = PostThreadMessage(ID1, 0x00404, 0,0 );

 
참고 사이트 및 서적

Windows Via C/C++

http://msdn2.microsoft.com/en-us/library/aa904937(VS.85).aspx

http://windows-programming.suite101.com/article.cfm/win32_message_processing_primer


*출처 :

http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNo=20&no=8026&ref=8026

gray_dilation_shape(m_hoSource, &ImageMax, 1.5, 1.5, "rectangle");              // Gray Level 확장

threshold(ImageMax, &Region, 140, 255);                                         // Threshold 찾기

connection(Region, &ConnectedRegions);                                          // 지정영역연결

HTuple lStart[2], lLast[2];                                                    // 영역지정값    

// 찾을영역지정

lStart[0] = (m_htImgWidth  / 2) - (lTipRgnWidth  * 0.5 * PIXEL_UNIT_ANTI);      // 좌상단 위치 지정 (가로)

lStart[1] = (m_htImgHeight / 2) - (lTipRgnHeight * 0.5 * PIXEL_UNIT_ANTI);      // 좌상단 위치 지정 (세로)

lLast[0]  = (m_htImgWidth  / 2) + (lTipRgnWidth  * 0.5 * PIXEL_UNIT_ANTI);      // 우하단 위치 지정 (가로)

lLast[1]  = (m_htImgHeight / 2) + (lTipRgnHeight * 0.5 * PIXEL_UNIT_ANTI);      // 우하단 위치 지정 (세로)

// 중심을 기준으로 검사 영역 설정

clip_region(ConnectedRegions, &RegionClipped, lStart[1],lStart[0],lLast[1],lLast[0]);  

select_shape(ConnectedRegions, &SelectedRegions1, "width", "and",10, 55);       // 지정크기영역만찾기(너비)

select_shape(SelectedRegions1, &SelectedRegions2, "height", "and",10, 55);      // 지정크기영역만찾기(높이)

select_shape(SelectedRegions2, &RegionTrans, "area", "and",100, 2700);          // 지정크기영역만찾기(영역)

shape_trans(SelectedRegions, &RegionTrans, "rectangle1");                       // 영역을변경

 

// 이하 이부분은 동일함 어차피 한 개의 영역만 구하고 화면 표시하는 부분이므로..

count_obj(RegionTrans, &SelectNum);                                             // 구한 영역 개수 구하기

long nNum;

tuple_int(SelectNum, &nNum);                                                    // 구한 개수를 일반 상수로 변경

// 구한 개수가 하나일 경우에만 다음과 같이 처리 하나 이상일 경우 에러 처리

HTuple X,Y, HalfX, HalfY;

area_center(RegionTrans, &Area, &Row, &Column);                                 // 구한 영역 중심값 구하기

// 영역 계산부분

// 현재 구한 부분을 전체 길이의 절반으로 뺀값이 중심부터 떨어진 값임

X = Column - (m_htImgWidth * 0.5);                                              // 가로축의 부분 계산

Y = Row - (m_htImgHeight * 0.5);                                                // 세로축 부분 계산

tuple_int(X, &lWidth);                                                          // 구한 값을 일반 상수로 변경

tuple_int(Y, &lHeight);

// 구한 결과값을 픽셀당 유니트 크기로 계산하기

nResultX = lWidth  * PIXEL_UNIT;                                                // PIXEL_UNIT은 미리 정의함

nResultY = lHeight * PIXEL_UNIT;

set_color(m_htDisp, "red");                                                     // 표시색상

set_tposition(m_htDisp, 10, 10);//nZoomScale + 10, nZoomScale + 10);            // 텍스트 표시 위치 설정

write_string(m_htDisp, "X : " + nResultX + " Y : " + nResultY);                 // 결과값표시

// 구한 영역을 외곽선만 표시함

set_line_width(m_htDisp, 1);                                                    // 굵기선택

set_draw(m_htDisp, "margin");                                                   // 외곽만표시

set_color(m_htDisp, "blue");                                                   // 표시색상 변경

disp_obj(RegionTrans, m_htDisp);                                               // 영역그리기

+ Recent posts