링크 : http://support.microsoft.com/kb/190351/ko 

한마디로 자식 프로세스를 생성해서 Input, Output으로 주고 받는 방법이다.

 

참고 : http://www.tipssoft.com/bulletin/board.php?bo_table=update&wr_id=941

팁스소프트의 좋은 예제

저작자 표시 비영리 변경 금지
신고
posted by 뚱2

링크  1 : http://bobmoore.mvps.org/Win32/w32tip26.htm

링크  2 : http://november11.tistory.com/55

 

링크 1은 프레임워크를 조금 수정해서 모달리스로 만드는 방법이고

링크 2는 WindowPosChanging을 이용한 방법이다.

둘다 테스트 해본결과 링크 2번이 구조도 덜 바꾸고 편했다.

저작자 표시 비영리 변경 금지
신고
posted by 뚱2

링크 : http://www.codeproject.com/Articles/14500/Detecting-Hardware-Insertion-and-or-Removal

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

저작자 표시 비영리 변경 금지
신고

'C/C++ > VC++ / MFC' 카테고리의 다른 글

[VC++] DevCon 사용법  (0) 2013.05.31
[MFC] Dialog 베이스로 시작시 숨기기  (0) 2013.05.31
[VC++] Detecting Hardware Insertion and/or Removal  (0) 2013.05.30
[ATL] ATL Com Programming  (0) 2013.05.24
[COM] Com Event Handling  (0) 2013.05.24
[VC++] IOCP 프로그래밍  (1) 2013.05.21
posted by 뚱2

* This global function can be used to extract a substring from a given source string.

BOOL AFXAPI AfxExtractSubString (
   CString& rString,
   LPCTSTR lpszFullString,
   int iSubString,
   TCHAR chSep = '\n'
);

* Sample Source
// The following example extracts a series of name, value pairs from a
// given source string:

// Input string consisting of a number of name, value pairs
LPCTSTR lpszSource = _T("\"Name\"=\"John Smith\"\n")
   _T("\"Company\"=\"Contoso, Ltd\"\n\"Salary\"=\"25,000\"");

CString strNameValue; // an individual name, value pair

int i = 0; // substring index to extract
while (AfxExtractSubString(strNameValue, lpszSource, i))
{
   // Prepare to move to the next substring
   i++;

   CString strName, strValue; // individual name and value elements

   // Attempt to extract the name element from the pair
   if (!AfxExtractSubString(strName, strNameValue, 0, _T('=')))
   {
      // Pass an error message to the debugger for display
      OutputDebugString(_T("Error extracting name\r\n"));
      continue;
   }

   // Attempt to extract the value element from the pair
   if (!AfxExtractSubString(strValue, strNameValue, 1, _T('=')))
   {
      // Pass an error message to the debugger for display
      OutputDebugString(_T("Error extracting value element\r\n"));
      continue;
   }

   // Pass the name, value pair to the debugger for display
   CString strOutput = strName + _T(" equals ") + strValue + _T("\r\n");
   OutputDebugString(strOutput);
}

 
저작자 표시
신고
posted by 뚱2

프로그램 업데이트 목록을 만들다 보면은 ListCtrl에 업데이트 목록을 넣어두고
업데이트를 할때마다 리스트 현재 행을 변경시킬때가 있다 그럴때 유용하다.

    // 먼저 현재 선택상태를 해제합니다
    m_listResult.SetItemState( -1, 0, LVIS_SELECTED|LVIS_FOCUSED );
    // 원하는 아이템을 선택합니다
    m_listResult.SetItemState(m_nCurrentItem, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
    // 선택된 아이템을 표시합니다
    m_listResult.EnsureVisible(m_nCurrentItem, false);
    // 리스트 컨트롤에 포커스를 맞춥니다
    m_listResult.SetFocus(); 
저작자 표시
신고
posted by 뚱2

물론 MultiByteToWideChar API를 사용하면  Ansi->Unicode로 전환할수 있습니다.

MultiByteToWideChar를 보시면 알겠지만 인자가 많습니다. ㅡㅡ;

int MultiByteToWideChar(
  UINT CodePage, 
  DWORD dwFlags,         
  LPCSTR lpMultiByteStr, 
  int cbMultiByte,       
  LPWSTR lpWideCharStr,  
  int cchWideChar        
);

이럴때 MFC에서만 사용할수 있는 꼼수

char szBuffer[] = "Ansi 스트링 입니다.";
CString strUnicode = (CString)szBuffer;

이렇게만 하면 끝났습니다.
다만 그냥 컨버팅 되는게 아니라
프로그램 베이스가 Unicode 기반으로 작성된 프로그램에서
Ansi 문자열을 Unicode 기반으로 컨버팅 하실때 편하게 사용하실수 있습니다.

소스를 쫓아 들어가보면 알겠지만

형변환 내부적으로 MultiByteToWideChar 함수를 호출하고 있습니다.

// 데이터 길이 가져오는 함수
static int __cdecl GetBaseTypeLength( _In_z_ LPCSTR pszSrc ) throw()
{
    // Returns required buffer size in wchar_ts
    return ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pszSrc, -1, NULL, 0 )-1;
}

// 데이터 변환 하는 함수
static void __cdecl ConvertToBaseType( _Out_cap_(nDestLength) LPWSTR pszDest
, _In_ int nDestLength, _In_z_ LPCSTR pszSrc, _In_ int nSrcLength = -1) throw()
{
    // nLen is in wchar_ts
    ::MultiByteToWideChar( _AtlGetConversionACP()
                          , 0, pszSrc, nSrcLength, pszDest, nDestLength );
}

그런데 막상 해보면 글자가 한글이 깨집니다.
이유는 http://msdn.microsoft.com/ko-kr/library/w1sc4t4k(VS.80).aspx
문자열 변환 보시면 알겠지만 기본 코드 페이지가 변경되었습니다.


문자열 변환

Visual C++ 6.0의 ATL 3.0 및 그 이전 버전에서는 atlconv.h의 매크로를 사용하는 문자열 변환이 항상 시스템의 ANSI 코드 페이지(CP_ACP)를 사용하여 수행되었습니다. Visual C++ .NET의 ATL 7.0부터는 _CONVERSION_DONT_USE_THREAD_LOCALE이 정의되지 않은 경우 문자열 변환이 현재 스레드의 기본 ANSI 코드 페이지를 사용하여 수행됩니다. _CONVERSION_DONT_USE_THREAD_LOCALE이 정의된 경우에는 이전과 같이 시스템의 ANSI 코드 페이지가 사용됩니다.

CW2AEX 등의 문자열 변환 클래스를 사용하면 변환에 사용할 코드 페이지를 해당 생성자에 전달할 수 있습니다. 코드 페이지를 지정하지 않으면 해당 클래스에서는 매크로와 동일한 코드 페이지를 사용합니다.

자세한 내용은 ATL and MFC String Conversion Macros를 참조하십시오.


결국 컨버전 할때 내부적으로

inline UINT WINAPI _AtlGetConversionACP() throw()
{
#ifdef _CONVERSION_DONT_USE_THREAD_LOCALE
    return CP_ACP;
#else
    return CP_THREAD_ACP;
#endif
}

이 함수를 호출하는데 _CONVERSION_DONT_USE_THREAD_LOCALE 매크로가 없기 때문에 CP_THREAD_ACP 코드
페이지가 작성됩니다.

그래서 매크로를 프로젝트에 추가(Property Pages->Configuration Properties->C/C++->Preprocessor->Preprocessor Definitions)해주고

Rebuild All 해서 사용하시면 됩니다.

저작자 표시
신고
posted by 뚱2

MFC를 사용 할 때 전역적으로 사용할수 있는 API 앞머리에 Afx가 붙습니다.
그중 현재 프로그램의 Instance Handle을 구할수 있는 API입니다.

AfxGetInstanceHandle();

그런데 이걸 Winapi로 하면 어떻게 될까요?  우선 GetWindowLong API를 이용하면 해결됩니다.
// 원형
LONG GetWindowLong(          
    HWND hWnd,
    int nIndex
);

아래와 같이 호출해 주시면 됩니다.  hWnd는 호출하는 쪽의 윈도우 핸들 입니다.
GetWindowLong(hWnd, GWL_HINSTANCE);

저작자 표시
신고
posted by 뚱2
VC++에서 ADO를 사용하는 방법은 크게 2가지가 있다.

1. OLE DB SDK라이브러리를 이용하는 방법
2. #import를 이용하여 Type Library를 이용하는 방법

전 개인적으로 2번째 방법을 선호합니다.
그리고 Type Library를 import 하면 스마트 포인터를 사용할수 있기때문에 편리합니다.

#import를 할려면 msadoxx.tlb 파일이나 msadoxx.dll 파일이 필요합니다.
ado는 버전별로 있기때문에 본인에게 맞는 버전을 사용하면 됩니다.

import할 파일은 C:\Program Files\Common Files\System\ado\ 에 있습니다.
MFC를 이용해서 프로그래밍을 한다면 StdAfx.h에 선언해 주는게  편합니다.
StdAfx.h에 선언하지 않으면 사용하는 곳마다 계속 선언을 해줘야 합니다.

//StdAfx.h
//...
#import "C:\\Program Files\\Common Files\\System\\ado\\msado26.tlb" \
        no_namespace rename("EOF", "adoEOF")
//...

type library를 임포트 할려면 .tlb라는 파일이 필요한데 ado는 .dll에도 type library가 저장되어 있습니다.
따라서 .tlb, .dll 둘중에 아무거나 임포트 하시면 됩니다.
namespace를 사용하지 않게 옵션을 주어서 코딩시 편하게 할 수 있습니다.
간혹 이름 충돌이 발생할수 있는데 그럴때는 rename_namespace("새로운이름") 옵션으로 이름을 변경해
주시면 됩니다.

rename("EOF", "adoEOF")는 혹 다른곳에서 EOF를 사용함으로 해서 충돌나는 것을 방지해줍니다.
저작자 표시
신고
posted by 뚱2

저는 대부분 MFC로 응용프로그램을 만들때 공유 DLL로 MFC 라이브러리 포함을 선택합니다. 

Static Library로 해서 소스코드가 커지는게 싫기도 하고

제 프로그램 개발방식이 exe +  확장 dll로 구성되어 있기때문에(확장 dll이 많게는 20개 이상도 됩니다.)

MFC dll 하나더 포함된다고 관리가 불편해 지는 것도 아니기에 소스크기를 줄일려고 DDL로 사용합니다.

그러지만은 디버깅시에는 MFC소스 코드를 쫓아가기 힘듭니다.

왜!! MFC 소스 코드를 쫓아가야 하냐?? 제가 만든 오류와 버그가 MFC쪽 소스코드에서 잡히는 경우가 있기때문입니다.

MFC 소스코드를 보면은 ASSERT로 Validation체크를 많이 해 놓는데 이게 Debug시에만 나타납니다.


그런데 그 소스 코드라인이 제 코드가 아니라 MS MFC 코드 속입니다.
결국 MFC 소스코드를 쫓가가서 직접 눈으로 확인해야 합니다.

이럴때는 Static Library로 연결해 놓으면 디버깅을 걸어서 소스코드를 쫓아갈수 있습니다.

저작자 표시
신고
posted by 뚱2

1. 제   목 :  Programming Windows with MFC Second Edition
2. 출판사 : Compeople
3. 저   자 : Jeff Prosise
4. 가   격 : 45,000원
5. 난이도 : 중급 (★★★★☆)
6. 판   매 : 절판
7. 평   가 : ★★★★☆

    다른 사람들이 다 MFC가 사양길이라고 할 때... (2005년부터 시작했습니다. ㅡㅡ;)
    그때 MFC 관련서적 이것 저것 구입했습니다. 대략 유명한건 거의다 구입한것  같습니다. 
    이 책은 절판되어서 최근에 친한 동생이 가지고 있는걸 받았습니다.
    다 살펴보진 않았지만 책의 내용은 정말 좋습니다.
    처음에 하나 하나 직접 클래스도 만들다가 나중에는 Class Wizard를 사용함으로 해서
    자동으로 생성되는 코드들에 대한 거부감을 줄인것도 처음 MFC를 시작하시는 분들께 좋을 것 같습니다.
    API 책 한권과 이책 한권만 있으면 대부분 어플리케이션을 개발하는데 크게 문제 없을 것 같습니다.
    책의 번역수준은 그리 좋지않지만 그것보다 오타가 많습니다. 특히 소스코드에 flag 설정하는 부분에서
    | (bit or 연산자)가 왜 그리 많이 빠졌는지... 
    그렇지만 다른 MFC 관련서적을 몇권 보셨다면 이해하는데 크게 무리가 없습니다.
    원서의 압박이 있으신 분은 MFC에 대한 최선의 선택이 되지 않을까 합니다.
저작자 표시
신고
posted by 뚱2
MFC에서 COM를 사용하기 위해서는 스레드 로딩시에  CoInitialize()를 호출해 주어야 합니다.
저는 ADO를 통해서 Oracle에 접근하기 위해서 사용했습니다.
단순한 생각으로 처음부터 DB에 연결해서 주구장창 하나로 사용하려고 했습니다.
그래서 다중접속 부분의 동시접속 문제는 CriticalSection을 이용했는데
알고 보니 이게 좋은 방법이 아니었습니다.
그래서 각 유저가 접속할때마다 DB를 Open하고 쿼리 날리고 DB를 Close 할려고 했는데
CreateInstance를 생성할때마다 스마트포인터가 NULL로 되더군요..
알고 봤더니 COM을 MFC에서 사용하기 위해서는
CoInitialize를 호출하는데 이건 스레드당 한개씩 오픈해야 한다는 것 입니다.
제가 다중접속을 위해서 별도의 스레드로 소켓을 이용한 프로그래밍을 했는데
각각 별도의 스레드에서 DB를 접속할려고 하니 안되는 거였습니다. ㅡㅡ;
결국 스레드당 접속을 한 결과 접속을 잘 해결되었습니다.

ADO ? COM 사용시 주의사항??

1. CoInitialize()와 CoUninitialize()는 꼭 짝으로 이뤄서 사용하자 :
   C++이라면 클래스로 만들어서 생성자에서 CoInitialize()하고 소멸자에서 CoUninitialize()하면
   좋겠죠
2. ADO 사용을 편하게 하기 위해서 스마트 포인터를 사용하는데... 스마트 포인터는 내부적으로
   소멸자에서 Release()를 호출해 줍니다. 따라서 명시적으로 Release()를 호출하면은 안됩니다.

하나라도 정확하게 알고 사용하는거와
모르고 사용하는건 큰 차이가 있을을 다시 한번 느꼇습니다.
이거 배워야 할게 너무도 많네요... ^^

 
신고
posted by 뚱2