LNK2005 에러 처리

역시.. LNK2005에 대한 error message로 인하여.. 거의 반나절이나 되는 시간을 까먹었다.
이렇게 편한 internet이 있는줄도 모르고...... 문명의 뒤에 있는 듯한 이 느낌...... T.T
여튼 아래와 같은 이유로 LNK2005 error가 발생한다.
아래와 같은 이유로.. 알아서.. 해결할 수도 있겠다..

---------------------------------------------------------------------------------------------------------------------

발췌 : http://blog.naver.com/rinbo7

MS Visual Studio를 사용하다가 다음과 같은 링크 에러를 보았다.

 

msvcrt.lib(MSVCRT.dll) : error LNK2005: _atoi already defined in libcmt.lib(atox.obj)

msvcrt.lib(MSVCRT.dll) : error LNK2005: _strchr already defined in libcmt.lib(strchr.obj)

msvcrt.lib(MSVCRT.dll) : error LNK2005: _strstr already defined in libcmt.lib(strstr.obj)

msvcrt.lib(MSVCRT.dll) : error LNK2005: __stricmp already defined in libcmt.lib(stricmp.obj)

msvcrt.lib(MSVCRT.dll) : error LNK2005: __setmbcp already defined in libcmt.lib(mbctype.obj)

nafxcw.lib(nolib.obj) : warning LNK4098: defaultlib "mfc42.lib" conflicts with use of other libs; use /NODEFAULTLIB:library

nafxcw.lib(nolib.obj) : warning LNK4098: defaultlib "mfcs42.lib" conflicts with use of other libs; use /NODEFAULTLIB:library

libcmt.lib(crt0init.obj) : warning LNK4098: defaultlib "msvcrt.lib" conflicts with use of other libs; use /NODEFAULTLIB:library

 

위에서 중복 선언되었다고 하는 함수들은 CRT library인데 뭐가 중복 선언되었다고 하는 것인지 알 수가 없어 한참을 삽질하다가 해결책을 구글링을 통해 발견했다.

 

 

- 발췌문 -

 

프로그램에서 사용되는 모든 라이브러리의 형태를 일치 시켜야 합니다. 윈도우 라이브러리는 3가지 형태가 있다네요.

 

1. 싱글쓰레드, 정적 라이브러리 링크 : /ML : libc*.* 이용

2. 멀티쓰레드, 정적 라이브러리 링크 : /MT : libcmt*.* 이용

3. 멀티쓰레드, 동적 라이브러리 링크 : /MD : msvcrt*.* 이용


그런데 중요한 것은 위의 3가지 형태의 라이브러에 동일한 함수들이 존재한다는 거죠. 그래서 링크도중에 2개 이상의 파일을 찾게되면 당연이 중복으로 존재하는 함수가 존재하게 되어 충돌하게 됩니다.

 

이를 원천적으로 해결하려면 프로젝트에 연관된 모든 프로그램을 3가지 중 한가지 형태로 빌드를 하면됩니다. 제작 중인 프로젝트에 사용되는 모든 라이브러리도 동일한 링크 형태로 빌드된 것이 링크되면 됩니다.


예를 들어서 dll을 사용하는 프로젝트가 /MDd 옵션을 사용하여 컴파일 한다면 이 프로젝트에서 사용되는 모든 라이브러리도 /MDd로 컴파일 된것을 준비해야 합니다.

[출처] LNK2005 에러 처리|작성자 딸기

by Yanagi | 2008/08/15 11:33 | 트랙백

MFC - 다이얼로그 생성시 발생되는 메세지들...

출처 : http://namacin.egloos.com/1368314

MFC - 다이얼로그 생성시 발생되는 메세지들...

다이얼로그가 생성될 때 발생되는 메세지의 순서로는

DoModal()
PreSubclassWindow()
OnNcCreate()
OnNcCalcSize()
OnCreate()
OnSize()
OnMove()
OnSetFont()
OnInitDialog()
OnWindowPosChanging()
OnMove()
OnWindowPosChanged()
OnWindowPosChanging()
OnNcActivate()
OnActivate()
OnShowWindow()
OnWindowPosChanging()
OnNcPaint()
OnEraseBkgnd()
OnChildNotify()
OnCtlColor()
OnWindowPosChanged()
OnPaint()
OnCtlColor()
OnCtlColor()
OnNcHitTest()
OnSetCursor()
PreTranslateMessage()
OnMouseMove()
OnNcHitTest()
OnSetCursor()
PreTranslateMessage()


클래스 위자드에서 메세지 필터를 Window로 주고 발생하는 모든 메세지에 대해서
간단한 문자 출력용 핸들러를 주었다.

이 상황에서 아무것도 없는 기본 다이얼로그 화면을 DoModal() 함수로 띄웠을 때
발생하는 메세지들을 캡쳐한것이다.

어떠한 핸들러들은 afx_msg 함수로 메세지 맵에 등록되고 어떠한 함수들은
vitual로 선언되며 메세지 맵에 등록되지 않았다. 이렇게 구분되는 기준은 무얼까?


%%
메세지 맵에 등록되는 함수(핸들러) 들은 정말 윈도가 뿌려대는 메세지에 대한
핸들러이고 virtual로 선언되는 함수들은 메세지에 대한 핸들러가 아니라
프로세스가 진행되면서 당연히 호출되는 함수들이 아닐까 생각된다.

 

어떠한 핸들러들은 publc으로, 어떠한 핸들러들은 protected로 선언된다.
(메세지 맵에 등록된 핸들러들은 모두 protected이다.)

중요한지 아닌지는 모르겠지만 차근차근 알아봐야할 내용들..

 


[메세지에 대한 설명은 www.winapi.co.kr 에서 발췌]

DoModal -
PreSubclassWindow -

WM_NCCREATE -
WM_NCCALCSIZE -
WM_CREATE -
WM_SIZE -
WM_MOVE -
WM_SETFONT -
WM_ONINITDIALOG -
 다이얼로그가 메모리에 만들어지고 화면에 보이기 적전에 보내진다고 한다.
 오버랩드 윈도우의 WM_CREATE에 해당한다는데...
 
WM_WINDOWPOSCHANGING -
WM_MOVE -
WM_WINDOWPOSCHANGED -
WM_WINDOWPOSCHANGING -
WM_NCACTIVATE -
 비 작업영역(client영역을 제외한 영역을 말하는것이 아닐까..)에 대한 활성
 또는 비 활성화시 변경되는 내용이 있을 때 보내진다고 한다.
 
WM_ACTIVATE -
 WM_NCACTIVATE가 비 작업 영역에 대한 메세지라면 이 메세지는 작업영역에 대한
 처리를 위한 메세지..

WM_SHOWWINDOW -
 윈도우의 보임 상태가 변경되기 직전에 보내진다고 한다. WS_VISIBLE 스타일을 가진 윈도우가
 생성될 때도 보내진다고 한다.
 
WM_WINDOWPOSCHANGING -
WM_NCPAINT -
 비 작업 영역을 그려야 할 때 발생한다고 한다
 
WM_ERASEBKGND -
 윈도우 크기가 변경 되었거나 다른 윈도우에 가려진 부분이 드러났다거나 할 때 배경을 지우기 위해
 이 메셎가 보내진다고 함. WM_PAINT에서 출력하기 전에 먼저 그려진 내용을 지워야 하는데 이 메세지에
 대해 처리를 하지 않으면 "윈도 클래스에 등록된!!" 디폴트 배경 브러시로 지운다고함.
  
 %% 윈도 클래스 배경 브러시가 NULL 일경우 아무것도 하지 않음.
 
WM_CHILDNOTIFY -
WM_WINDOWPOSCHANGING -
WM_PAINT -
 1. 윈도우가 처음 생성되었을 때
 2. 윈도우의 위치가 이동되었을 때
 3. 윈도우의 크기가 변경, 최소, 최대화 되었을 때
 4. 다른 윈도우에 가려져 있다가 드러날 때
 5. 스크롤 될 때
 발생한다고 한다.
 
WM_CTLCOLOR -
 윈도우가 그려질 필요가 있을 때 발생되어 브러시의 색상을 지정하게 된다.
 
WM_CTLCOLOR -
WM_NCHITTEST -
 마우스를 이동하거나 버튼을 누르거나 놓을 때마다 발생. 커서가 있는 위치가 윈도우의 어디쯤인지를
 윈도우에게 질문을 하며 운영체제닌 이 메세지의 리턴값에 따라 마우스를 처리한다고 한다
 
WM_SETCURSOR -

PreTranslateMessage -

뒤로

WM_MOUSEMOVE
WM_NCHITTEST
WM_SETCURSOR

의 메세지가 연속적으로 나오는데 이 메세지는 다이얼로그 생성과는 관계가 없는듯..
또, 각 메세지들의 중간중간에 WindowProc, DefWindowProc, WM_CTLCOLOR, PreTranslateMessage
메세지가 매우 자주 섞여 나왔다.

by Yanagi | 2008/05/23 16:32 | 트랙백

[함수] SetWindowPos

SetWindowPos( )

원형

BOOL SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);

인수

hWnd : 이동 대상 윈도우의 핸들

hWndInsertAfter : 윈도우의 Z순서를 지정한다. 이 인수가 지정하는 윈도우 앞에 hWnd가 배치되는데 단 hWnd가 액티브 상태일 경우 이 인수가 지정하는 윈도우 핸들은 무시된다. 또는 다음과 같이 Z순서를 지정하는 값들이 올 수 있다.

설명

HWND_BOTTOM

hWnd윈도우를 Z순서의 제일 바닥으로 보낸다. 만약 이 윈도우가 항상 위(Top Most)속성을 가지고 있었다면 이 속성은 해제되고 모든 윈도우의 제일 아래쪽에 배치된다.

HWND_NOTOPMOST

항상 위 속성을 가지지 않은 윈도우 중 제일 위쪽에 배치된다. , 항상 위 속성을 가진 윈도우 바로 아래에 배치된다. 이 옵션은 항상 위 속성을 해제할 때 사용된다. 만약 항상 위 옵션을 가지고 있지 않다면 이 옵션은 아무런 효과도 가지지 않는다.

HWND_TOPMOST

항상 위 속성을 설정한다. 항상 위 속성을 가지지 않는 윈도우들보다 위쪽에 배치된다.

HWND_TOP

Z순서상의 제일 위쪽에 배치한다.

X,Y : 윈도우의 새로운 좌상단 좌표를 지정한다. 픽셀 단위이다.

cx, cy : 윈도우의 새로운 폭과 높이를 지정한다. 픽셀 단위이다.

uFlags : 위치와 크기 변경에 대한 여러 가지 옵션들이며 플래그들을 조합하여 지정할 수 있다.

플래그

설명

SWP_ASYNCWINDOWPOS

이 함수를 부른 스레드와 윈도우를 소유한 스레드가 다른 입력 큐를 사용할 경우 시스템은 윈도우를 소유한 스레드에게 요구를 포스팅하기만 한다. 이는 호출 스레드가 다른 스레드가 요구를 처리하는 동안 블럭되는 것을 방지한다.

SWP_DEFERERASE

WM_SYNCPAINT 메시지 발생을 금지한다.

SWP_DRAWFRAME

윈도우 주변에 프레임을 그린다.

SWP_FRAMECHANGED

SetWindowLong으로 경계선 스타일을 변경했을 경우 새 스타일을 적용한다. 이 플래그가 지정되면 크기가 변경되지 않아도 WM_NCCALCSIZE 메시지가 전달된다.

SWP_HIDEWINDOW

윈도우를 숨긴다. 이 경우 이동과 크기 변경은 무시된다.

SWP_NOACTIVATE

크기 변경 후 윈도우를 활성화시키지 않는다.

SWP_NOCOPYBITS

이 플래그가 지정되지 않으면 작업영역의 내용이 저장되었다가 크기나 위치변경 후 다시 작업영역으로 복사된다. 이 플래그가 지정되면 이런 저장을 하지 않는다.

SWP_NOMOVE

위치는 이동하지 않고 크기만 변경한다. X,Y인수가 무시된다.

SWP_NOOWNERZORDER

소유자의 Z순서를 변경하지 않는다.

SWP_NOREDRAW

크기, 위치를 바꾼 후 그리기를 하지 않는다. 해당 윈도우는 물론이고 이 윈도우에 의해 다시 드러나는 윈도우도 다시 그리기를 하지 않는다. 이 플래그를 주었을 경우 프로그램은 필요한 부분을 즉시 무효화시켜 다시 그리도록 해 주어야 한다.

SWP_NOREPOSITION

=SWP_NOOWNERZORDER

SWP_NOSENDCHANGING

윈도우에게 WM_WINDOWPOSCHANGING 메시지를 보내지 않는다.

SWP_NOSIZE

크기는 변경하지 않고 위치만 이동한다. cx, cy 인수가 무시된다.

SWP_NOZORDER

현재의 Z순서를 그대로 유지한다. hWndInsertAfter 인수를 무시한다.

SWP_SHOWWINDOW

윈도우를 보인다. 이 경우 이동과 크기 변경은 무시된다.

 

리턴

성공하면 0이 아닌 값을 리턴하며 에러 발생시 0을 리턴한다.

설명

이 함수는 윈도우의 위치, 크기, Z순서를 동시에 또는 일부만 변경할 때 사용된다. 예를 들어 크기는 그대로 두고 위치만 변경하고자 한다거나 위치와 크기는 그대로 두고 Z순서만 변경하고자 할 때 사용한다. MoveWindow 함수는 크기와 위치를 항상 같이 변경하지만 이 함수는 SWP_NOSIZE, SWP_NOMOVE 플래그로 위치와 크기를 개별적으로 변경할 수 있다.

또한 이 함수는 Z순서를 변경하기 위한 목적으로, 특히 항상 위(Top Most) 속성을 토글하기 위한 용도로도 많이 사용되는데 두번째 인수에 HWND_(NO)TOPMOST를 줌으로써 이 속성을 토글할 수 있다. 이 함수로 항상 위 속성을 설정하면 이 윈도우에 소유된 윈도우도 항상 위 속성을 같이 가지게 된다. 그러나 이 윈도우를 소유한 윈도우는 영향을 받지 않는다. 반대로 이 함수로 항상 위 속성을 해제하면 이 윈도우에 소유된 윈도우와 이 윈도우를 소유한 윈도우의 항상 위 속성이 모두 해제된다.

일반적으로 항상 위 속성을 가지지 않은 윈도우가 항상 위 속성을 가진 윈도우를 소유할 수는 있지만 반대는 불가능하다. 왜냐하면 소유된 윈도우는 소유한 윈도우보다 Z순서의 위쪽에 있어야 하므로 소유한 윈도우만 항상 위 옵션을 가질 수는 없기 때문이다. 이렇게 되면 항상 위 옵션을 가지는 윈도우의 차일드로 열려 있는 대화상자가 밑으로 숨어 버리는 현상이 발생할 수 있다. SetWindowPos 함수는 이 모든 처리를 다 해 주므로 항상 위 스타일을 토글 할 때는 SetWindowLong으로 SWL_EXSTYLE을 조작하지 말고 반드시 이 함수를 사용해야 한다.

예제 1

다음 예제는 SetWindowPos 함수로 윈도우의 위치만 변경하는 방법과 항상 위 스타일을 토글하는 방법을 보여준다.

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

{

             HDC hdc;

             PAINTSTRUCT ps;

             char Mes[]="왼쪽=위치 변경, 오른쪽=항상 위 옵션 변경";

             static BOOL bTopMost=FALSE;

 

             switch(iMessage) {

             case WM_LBUTTONDOWN:

                           SetWindowPos(hWnd, HWND_NOTOPMOST,

                                        rand()%640, rand()%480, 0, 0, SWP_NOSIZE);

                           return 0;

             case WM_RBUTTONDOWN:

                           if (bTopMost) {

                                        SetWindowPos(hWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

                           } else {

                                        SetWindowPos(hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

                           }

                           bTopMost=~bTopMost;

                           return 0;

             case WM_PAINT:

                           hdc=BeginPaint(hWnd, &ps);

                           TextOut(hdc,10,10,Mes,lstrlen(Mes));

                           EndPaint(hWnd, &ps);

                           return 0;

             case WM_DESTROY:

                           PostQuitMessage(0);

                           return 0;

             }

             return(DefWindowProc(hWnd,iMessage,wParam,lParam));

}

왼쪽 버튼을 누르면 난수로 정한 새 위치로 윈도우를 옮기되 SWP_NOSIZE 플래그를 주어 크기는 변경하지 않도록 하였다. 오른쪽 버튼을 누르면 항상 위 옵션을 토글시킨다.

참고

함수

MoveWindow : 윈도우의 위치와 크기를 동시에 변경한다.

Platform

Windows 95 이상

본문

참조

 

 

written by http://www.winapi.co.kr

 

by Yanagi | 2008/05/23 11:12 | 트랙백

◀ 이전 페이지          다음 페이지 ▶