2013.07.10 21:53



 CWnd *pWnd = AfxGetMainWnd();
 HWND hWnd = pWnd->m_hWnd;


인스턴스 정보는 아래와 같은 방법으로 쉽게 얻어진다.

HINSTANCE hInst = AfxGetInstanceHandle();

신고


Posted by injunech
2013.07.09 12:40


 

CWinThread*     pThread = NULL;

static volatile bool  isThreadRunning;

 

//////////////////////////////////////////////////////////////////////////

//

//              AfxbeginThread에 등록되는 함수.

//              반드시 static (전역)함수여야 한다.

//

//////////////////////////////////////////////////////////////////////////

UINT MyThread(LPVOID lpParam)

{

        MyClass* pClass = (MyClass*) lpParam;

        int iReturn     = pClass->ThreadFunction();

        return 0L;

}

 

 

//////////////////////////////////////////////////////////////////////////

//

//              Thread 생성 함수

//

//////////////////////////////////////////////////////////////////////////

void MyClass::CreateThread(UINT _method)

{

        if(pThread!=NULL)

        {

                AfxMessageBox("thread가 이미 실행중입니다!");

                return;

        }

 

        pThread = AfxBeginThread( MyThread, this,

                THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);

       

        if(pThread == NULL)

                cout<<"Fail to create camera thread!!";

       

        pThread->m_bAutoDelete = FALSE;

        pThread->ResumeThread();

}

 

//////////////////////////////////////////////////////////////////////////

//

//              Thread 소멸 함수

//

//////////////////////////////////////////////////////////////////////////

bool MyClass::DestroyThread(void)

{

        if(NULL != pThread)

        {

                DWORD dwResult = ::WaitForSingleObject(pThread->m_hThread,INFINITE);

                 

                if(dwResult == WAIT_TIMEOUT)

                        cout<<"time out!"<<endl;

                else if(dwResult == WAIT_OBJECT_0)

                        cout<<"Thread END"<<endl;

               

                delete g_pThread;

 

                pThread = NULL;

        }

        return true;

}

 

//////////////////////////////////////////////////////////////////////////

//

//                      Thread 함수

//     

//////////////////////////////////////////////////////////////////////////

int MyClass::ThreadFunction( void )

{

 

        while ( isThreadRunning )

        {

               

                // Check to see if the thread should die.

                if( !isThreadRunning )

                        break;

 

                // 소스 입력...

                //

        }

        return returnValue;

}



 

[함수 설명]


CWinThread* AfxBeginThread(

   AFX_THREADPROC pfnThreadProc,

   LPVOID pParam,

   int nPriority = THREAD_PRIORITY_NORMAL,

   UINT nStackSize = 0,

   DWORD dwCreateFlags = 0,

   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL 

);

CWinThread* AfxBeginThread(

   CRuntimeClass* pThreadClass,

   int nPriority = THREAD_PRIORITY_NORMAL,

   UINT nStackSize = 0,

   DWORD dwCreateFlags = 0,

   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL 

);


// - msdn :http://msdn.microsoft.com/ko-kr/library/s3w9x78e(v=VS.80).aspx

thread를 생성할 때 사용한다.

pfnThreadProc : 함수의 주소가 들어간다. (반드시 정적함수여야 한다.)

pParam : 스레드로 실행할 함수에 인자로 전달되는 값으로 보통은 주소가 된다.

nPriority: 스레드의 우선순위를 지정한다. 보통으로 사용하기 위해서는 THREAD_PRIORITY_NORMAL 을 쓴다. 

nStackSize: 스레드의 최대 스택 크기를 지정한다. 0을 넣으면 프로세스 생성시 최초 실행되는 스레드의 크기와 같게  

할당된다.

dwCreateFlags: 스레드를 생성한 다음 즉시 실행할 것인지 아니면 대기했다가 실행할 것인지를 명시한다. 

CREATE_SUSPENDED를 사용하면 스레드는 실행되지 않고 대기하게 되며 이 경우 ResumeThread()

함수를 소출하여 스레드를 시작할 수 있다.


 

 


DWORD WaitForSingleObject( 

  HANDLE hHandle, 

  DWORD dwMilliseconds 

); 

// msdn - http://msdn.microsoft.com/ko-kr/library/aa450988

 

::WaitForSingleObject() 함수는 특정 object의 상태가 설정될 때 까지 현재 thread의 실행을 멈추는 역할을 한다. dwMilliseconds 시간만큼 기다리며 이 시간안에 object의 상태가 변화되면 값을 반환한다.

이때 반환값으로 WAIT_TIMEOUT이 반환되면, 기다리는 동안 object의 상태가 설정되지 않아서 그냥 반환했다는 것을 의미하며 WAIT_OBJECT_0를 반환했다면 object의 상태가 설정되어서 반환했다는 것을 의미한다.


여기서 hHandle에는 object의 핸들이나 프로세스의 핸들과 같은 각종 핸들이 들어간다.




[주의]


thread를 종료할 때 thread 함수 안에서 DestroyThread() 함수를 호출하면 thread가 정상적으로 종료 되지 않는다. (무한정 기다리게 되거나..)


그러므로 DestroyThread 함수는 반드시 thread 함수 밖에서 호출 해 줘야한다. (따로 종료 버튼을 만들거나, 메시지 방식 등..)

[출처] [MFC] mfc thread 사용하기 |작성자 hextrial


신고


Posted by injunech
2013.07.09 02:25




TrayIcon.zip


TrayIcon.Z01




1.  프로젝트 생성

-       형식 : MFC 응용프로그램

-       이름 : TrayIcon

-       응용프로그램 종류 : 대화상자 기반 (Dialog based)

2.  프로젝트 생성 후리소스 뷰의 아이콘 중 IDR_MAINFRAME을 자신이 원하는 모양으로 바꿔준다

3.  솔루션 뷰의 헤더파일 중 stdafx.h 파일의 아랫쪽 부분에 다음을 입력

(include 작업의 뒤쪽에 해 주는 것이 좋다.)

이것이 바로 사용자 정의 윈도우 메시지의 설정.(9번과 10번 과정을 꼭 해야함)

 

#define WM_DIALOG_SHOWWM_USER + 101  //다이얼로그감추기/보이기

#define WM_APP_EXIT               WM_USER + 102  //다이얼로그종료

#define WM_TRAYICON               WM_USER + 103  //트레이아이콘메시지

 

4.  CTrayIconMng 클래스를 추가한다기본 클래스는 Cobject.

5.  그리고 CTrayIconMng 클래스의 멤버변수와 함수를 추가 해 준다.

 

        // 트레이아이콘이생성되었는지여부 (True : 생성됨)

        bool m_bAdded;

        // 다이얼로그가감춰진상태인지여부 (True : 숨겨짐)

        bool m_bHide;

        // 팝업메뉴생성

        void MakePopupMenu(HWND hWnd, int x, int y);

        // 팝업메뉴의이벤트발생시처리함수

        void ProcTrayMsg(HWND hWnd, WPARAM wParam, LPARAM lParam);

        // 트레이아이콘생성

        BOOL AddTrayIcon(HWND hWnd);

        // 트레이아이콘제거

        BOOL DelTrayIcon(HWND hWnd);

 

6.  CTrayIconMng 클래스의 멤버함수 코드들을 다음과 같이 각각 작성한다.

// 팝업메뉴생성

void CTrayIconMng::MakePopupMenu(HWND hWnd, int x, int y)

{

  //팝업메뉴를생성하고메뉴구성

  HMENU hMenu = CreatePopupMenu();

  if(m_bHide)            //다이얼로그가감춰진상태라면

        AppendMenu(hMenu, MF_STRING, WM_DIALOG_SHOW, _T("다이얼로그보이기"));

    else                 //다이얼로그가숨겨진상태라면

        AppendMenu(hMenu, MF_STRING, WM_DIALOG_SHOW, _T("다이얼로그감추기"));

 

  AppendMenu(hMenu, MF_STRING, WM_APP_EXIT, _T("종료"));

 

  SetForegroundWindow(hWnd);//생성된팝업메뉴밖을클릭할때팝업닫기

  //팝업메뉴띄우기

    TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, 0, hWnd, NULL);

}

 

 

// 팝업메뉴의이벤트발생시처리함수

void CTrayIconMng::ProcTrayMsg(HWND hWnd, WPARAM wParam, LPARAM lParam)

{

  HMENU hMenu = NULL;

    POINT pos;

 

    if(lParam == WM_LBUTTONDOWN)

    {

        GetCursorPos(&pos);

         MakePopupMenu(hWnd, pos.x, pos.y); //팝업메뉴생성및출력

    }

}

 

// 트레이아이콘생성

BOOL CTrayIconMng::AddTrayIcon(HWND hWnd)

{

  if(m_bAdded)           //이미트레이아이콘이있다면종료

         return FALSE;

 

  NOTIFYICONDATA nid;    //아이콘을생성하여설정

    ZeroMemory(&nid, sizeof(NOTIFYICONDATA));

    nid.cbSize = sizeof(NOTIFYICONDATA);

    nid.hWnd = hWnd;

    nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;

    nid.uCallbackMessage = WM_TRAYICON;

    //sprintf((char*)nid.szTip, (char*)_T("TrayTest"));

 lstrcpy(nid.szTip, "TrayTest"); // tool tip 메세지

    nid.uID = 0;

    nid.hIcon = theApp.LoadIcon(IDR_MAINFRAME);

 

    if(Shell_NotifyIcon(NIM_ADD, &nid)==0) //트레이아이콘표시

        return FALSE;

  m_bAdded = true;      

    return TRUE;

}

 

// 트레이아이콘제거

BOOL CTrayIconMng::DelTrayIcon(HWND hWnd)

{

  NOTIFYICONDATA nid;

 

    ZeroMemory(&nid, sizeof(NOTIFYICONDATA));

    nid.cbSize = sizeof(NOTIFYICONDATA);

    nid.hWnd = hWnd;

    nid.uFlags = NULL;

    if(Shell_NotifyIcon(NIM_DELETE, &nid)==0) //트레이아이콘삭제

        return FALSE;

    return TRUE;

 

}

7.  CTrayIconDlg 에 멤버 변수 및 함수 추가       

// 트레이아이콘관리용객체

  CTrayIconMng m_myTray;

  // 트레이아이콘보이기/숨기기여부

  bool m_bHide;

  long OnTrayIcon(WPARAM wParam, LPARAM lParam);

  void OnAppExit(void);

void OnDialogShow(void);

 

8.  CTrayIconDlg  OnInitDialog() 함수의 마지막부분에 다음을 추가하여 프로그램이 시작됨과 동시에 트레이아이콘을 추가하게끔 함  

 m_myTray.m_bHide = m_bHide;

        m_myTray.AddTrayIcon(GetSafeHwnd());

        return TRUE;  // 컨트롤에 대한 포커스를 설정하지 않을 경우 TRUE를 반환합니다.

 

9.  CTrayIconDlg 에 다음의 함수를 추가 이들은 사용자 메시지 핸들러 역할을 한다

long OnTrayIcon(WPARAM wParam, LPARAM lParam);

void OnAppExit();

void OnToggleShow();

 

10. CTrayIconDlg의 메시지 맵에서 사용자 메시지 핸들러와 연결을 시켜준다

 

BEGIN_MESSAGE_MAP(CMyMessengerDlg, CDialog)

        ON_MESSAGE(WM_TRAYICON, OnTrayIcon)

        ON_COMMAND(WM_APP_EXIT, OnAppExit)

ON_COMMAND(WM_DIALOG_SHOW, OnDialogShow)

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

 

11. CTrayIconDlg 클래스의 함수들을 다음과 같이 지정 해 준다.

(이때, .cpp 파일에 #include "TrayIconMng.h" 가 포함되어야 한다)

 

//트레이아이콘을클릭했을때의메시지핸들러

long CTrayIconDlg::OnTrayIcon(WPARAM wParam, LPARAM lParam)

{

  m_myTray.ProcTrayMsg(GetSafeHwnd(), wParam, lParam);

  return 0;

}

 

//트레이아이콘팝업메뉴의종료메뉴메시지핸들러

void CTrayIconDlg::OnAppExit(void)

{

  m_myTray.DelTrayIcon(GetSafeHwnd());

  CDialog::OnCancel();

}

 

//트레이아이콘보이기/숨기기메뉴메시지핸들러

void CTrayIconDlg::OnDialogShow(void)

{

  if(!m_bHide) ShowWindow(false);       //보이는상태라면숨기고

  else ShowWindow(true);                //숨겨진상태라면보이게

  m_bHide = !m_bHide;

  m_myTray.m_bHide = m_bHide;

}

 

12.  컴파일 및 실행

신고


Posted by injunech
2013.07.08 21:09


1. 아이콘 변경하는 방법.

 

첫째, 우선 비쥬얼 스튜디오를 끈다.

둘째, "res" 폴더에 보면 "프로젝트이름.ico" 라는 파일이 있다. 이것을 본인이 원하는 아이콘으로 대체.

셋째. 비쥬얼 스튜디오를 열어서, 재컴파일 하면, 아이콘이 변경되어 있다.

 

- 주의 사항 -

반듯히 첫째 과정을 거쳐야 합니다.

 

2. 프로그램 버전 및 정보 고치기

 

프로젝트의 리소스뷰어에 보면, 프로그램 버전 및 정보에 관련된 리소스가 있습니다.

잘 찾아 보시면 있습니다.

이 부분을 수정해서, 고친다.

재컴파일 하시면 됩니다.

 

3. Release 로 배포하기

 

프로젝트 속성에 보면,

공유 DLL 을 사용할지, 정적 라이브러리를 사용할지 , 정적 API를 사용할지 등

여러가지 옵션이 있습니다.

그중 정적인것을 선택하시면 DLL 배포도 필요하지 않습니다.


MFC 제작된 프로그램을 다른 컴퓨터에서 실행하려고 하면 에러 메세지가 뜨면서 실행이 되질 않는다 (초기화 할 수 없다나..DLL이 없다나..)

    1) 프로젝트 속성->구성 속성(Configuration Properties)->일반(General)의 MFC사용(Use of MFC)를 Static Library 사용으로 바꾼다.

    2) 프로젝트 속성-> C/C++ -> 코드 생성(Code Generation)에서 런타임라이브러리(Runtime Library) 항목을  MD에서 MT로 변경해준다.

    3) Release 모드로 컴파일 한다.

이렇게 하면 런타임이 설치되지 않은 컴퓨터에서도 실행이 된다.




 

단 GDI+ 를 사용하시거나 다른 라이브러리를 사용하신 프로젝트라면 관련 라이브러리나 DLL 은 배포하셔야 합니다.

 

그리고 Release 로 재 컴파일 하면, 그것은 바로 배포가 가능합니다.

신고


Posted by injunech
2013.07.06 23:48


CString 사용 예제
 

1. 문자열 복사 하기

단순히 대입만 하면 된다.


CString str1("어쩌구");

CString str2;


str2=str1;       //대입

str2='A';        //단일문자

str2="ABC";   //문자열


2. 문자열 추출 하기

Left, Mid, Right 를 사용하여 추출한다. 직관적으로 왼쪽,중간,오른쪽이라는 것을 알 수 있다.


CString str1("ABCDE");

CString str2;


//왼쪽에서부터 i 개의 글자를 추출하여 Str2에 넣음

str2=str1.Left(i);


//오른쪽에서부터 i개의 글자를 추출하여 Str2에 넣음

str2=str1.Right(i);


//중간에 a번 건너뛰고 i개의 글자를 추출하여 Str2에 넣음

str2=str1.Mid(a,i);


EX) 

str2=str1.Left(3);

printf("%s",str2);       //"ABC"


str2=str1.Right(2);

printf("%s",str2);       //"DE"


str2=str1.Mid(2);

printf("%s",str2);       //"CDE"


str2=str1.Mid(2,2);

printf("%s",str2);       //"CD"


3.문자열 연결하기

신기하게도 더하기 처럼 사용한다.


CString str;


str = "ab";
str = str + "c" + "d";
str += "e";
printf( str );               // "abcde"


4.문자열 비교하기

비교하여 정수를 리턴한다


CString str( "ABC" );
int bRet;


bRet = str.Compare( "ABC" );
//  0 , 같음 "ABC" == "ABC"

bRet = str.Compare( "abc" );
// -1 , 작음 "ABC" < "abc"
 
bRet = str.Compare( "123" );
//  1 , 큼   "ABC" > "123"

bRet = str.CompareNoCase( "abc" );
//  0 , 같음 "ABC" == "abc"

bRet = str.CompareNoCase( "ABC" );
//  0 , 같음 "ABC" == "ABC"


// oprator ==, !=, <, >, <=, >=

( str == "ABC" ) ?  "true" : "false"         // true
( str != "ABC" )  ?  "true" : "false"        // false
( str <  "ABC" ) ?  "true" : "false"        // false
( str >  "ABC" ) ?  "true" : "false"        // false
( str <= "ABC" ) ?  "true" : "false"       // true
( str >= "ABC" ) ?  "true" : "false"       // true



5.문자열 검색하기

찾을 문자열을 쓰면 성공/실패 리턴



int nIndex;
CString str("abcde abc");


nIndex = str.Find( 'a' );
//  0, 성공

nIndex = str.Find( 'k' );
// -1, 실패

nIndex = str.Find( "bc" );
//  1, 성공

nIndex = str.Find( "bcdef" );
// -1, 실패

nIndex = str.Find( "abc", 5 );      //5번째 이후부터 찾고, 찾은 위치 리턴
//  6, 성공

nIndex = str.ReverseFind( 'e' );  //뒤에서부터 찾아 위치 리턴
//  4, 성공




6. 문자세트 검색하기

과연 쓸모가 있을까 하는 기능

가장 비슷한 문자열을 찾아 준다고 하는데...


int nIndex;
CString str( "abcde abc" );


nIndex = str.FindOneOf( "1c23e" );   //이것같은 경우는 c를 찾아서 위치값리턴한다.
//  2, 성공

nIndex = str.FindOneOf( "123" );       //같은게 없으니까 당연히 실패
// -1, 실패



7. 문자세트 추출하기

추출이 진짜 추출이 아닌것같다. 문자열 걸러내기가 더 어울리는 것같은데...ㅎ

 

CString str( "age is 30 ~*^^*" );
CString spnstr;
 

// str은 변하지 않습니다.
// 소문자 a ~ z 그리고 공백 문자가 포함된 문자열까지 추출합니다.

spnstr = str.SpanIncluding( "abcdefghijklmnopqrstuvwxyz" );

// str      출력시   "age is 30 ~*^^*"
// spnstr 출력시   "age is "

 

// "~!@#$%^&*()-=_+[]{},.<>/?;:'`" 를 포함하지 않는 문자열까지 추출합니다.

spnstr = str.SpanExcluding(" ~!@#$%^&*()_=+[]{},.<>/?;:'`" " );

// str      출력시    "age is 30 ~*^^*"
// spnstr 출력시    "age is 30"

 

 

 

8. 문자열의 공백 및 문자 제거하기

제거하고 원래 문자열에 저장까지...이걸쓸껄...ㅋ

 

CString str1( "  abcd \t\n" );
CString str2( "abcd1234" );
CString str3( "(***abcd1234***)" );
 
str1.TrimLeft();                //아무것도 안쓰면 공백 제거하기 왼쪽부터~
// "abcd \t\n"

 

str1.TrimRight();              //\t\n은 개행문자인데 따로 지정안해도 지워져버린다. 오른쪽~
// "abcd"

 

str2.TrimLeft( 'a' );           //특정문자 지정해서 지우기 왼쪽부터~
// "bcd1234"

 

str2.TrimRight( "234" );      //오른쪽부터~
// "bcd1"

 

str3.TrimLeft( "(*" );          //해봐야겠는데...
// "abcd1234***)"

 

str3.TrimRight( "*)" );         //왜 자동으로 **마저 지워지지?
// "abcd1234"

신고


Posted by injunech
2013.07.05 15:01


MFC로 프로그래밍 하면서 printf 함수를 사용하고 싶을 때가 있습니다.

VS 2008 이후 버전이라면 아주 간단히 해결됩니다.


stdafx.h 파일의 가장 앞쪽에 아래 한 줄을 추가해 주면 됩니다.

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


프로그램을 실행시키면 도스창이 같이 실행되고, printf 함수를 호출하면 도스창에 출력되게 됩니다.


신고


Posted by injunech
2013.07.05 11:42


'MFC를 이용한 채팅 프로그래밍 시작하기 (클라이언트)'을 통해 간단한 프로그램을 작성해 보았습니다.

참고자료로 비슷한 프로그램 코드 링크를 올려드립니다.




TalkClient.vol1.egg


TalkClient.vol2.egg



출처

http://cafe.naver.com/eztcp/263

신고


Posted by injunech
2013.07.05 11:40


'MFC를 이용한 채팅 프로그래밍 시작하기 (서버편)'을 통해 간단한 프로그램을 작성해 보았습니다.

참고자료로 비슷한 프로그램 코드 링크를 올려드립니다.



TalkServer.vol1.egg


TalkServer.vol2.egg


신고


Posted by injunech
2013.07.05 11:38


'MFC를 이용한 소켓 프로그래밍 시작하기 (클라이언트편)'을 통해 간단한 소켓 프로그램을 작성해 보았습니다.

해당 프로그램의 참고자료로 프로그램 코드 링크를 올려드립니다.



HelloClient.vol1.egg


HelloClient.vol2.egg


신고


Posted by injunech
2013.07.05 11:35


'MFC를 이용한 소켓 프로그래밍 시작하기 (서버편)'을 통해 간단한 소켓 프로그램을 작성해 보았습니다.

해당 프로그램의 참고자료로 프로그램 코드 링크를 올려드립니다.



HelloServer.vol1.egg


HelloServer.vol2.egg




신고


Posted by injunech