천객만래 [千客萬來] (It has an interminable succession of visitors)

LPSTR LPCTSTR 위험 CStrgin -> char 으로 변환




(LPSTR)(LPCTSTR)csTest은 위험하다.!!
-. 유니코드를 고려하지 않았을뿐 아니라
-. 위험하게 내부데이터를 접근합니다.
 
CString strPP;
char * chNN = (LPSTR)(LPCSTR)strPP;
이렇게 해서 chNN을 CString의 포인터로 가져 옵니다.

(LPSTR)(LPCSTR)strPP 이 부분 에서 이유는 MSDN을 찾아보시면 아시겠지만 CString은 const char * 으로 만 받을수 있답니다. 
그래서 (LPCTSTR)strPP 이런 형식으로도 사용합니다. 물론 const char *으로 return되겠죠.. 다시 char *을 필요하신다면  
char * chNN = (char *)(LPCTSTR)strPP; 이런 식으로도 사용합니다
 
char *pstr = (LPSTR)(LPCTSTR)str;        이 줄은 UNICODE인경우 
    char *pstr = (char *) (const wchar_t *) str;    입니다.
특히 wchar_t를 본래데이터형으로 보지 않을 경우
    char *pstr = (char *)(const unsigned short *)str;   입니다..
 
유니코드를 고려하지 않는다고 하더라도, CString이 제공하는 것은 const 가 붙은 형변환 밖에 없는데,
이걸 const 를 억지로 빼버리고는 마치 접근해서 고쳐도 되는 것처럼 보이게 되므로 
잘못사용하면 오류를 일으키며. 프로그램이 뻗을수도 있습니다.
 
const 변환은 받는 쪽에서 안고친다고 보고 CString이 자기 내부 메모리주소를 살짝 보여주는 건데.. 
그걸 char로 바꾸고 쓰려고 하면 당연히 에러가 발생 하겠죠...
보통 이런 문제는 char[50] 에서 처럼 .. "특정 위치의 글자를 바로 접근할 수 있냐..?"란 의문에서 생기는데 
이 문제는 CString만으로도 충분합니다.

CString이 operator[] 를 제공하고 있습니다.. operator를 이용 하면 됩니다.. 
str[23] 이렇게 마치 char[] 처럼 사용하실수 있습니다. 
물론 이때도 배열의 길이를 넘어서는 접근은 피해야 합니다.
C/C++의 배열이 제공못하는 길이를 CString은 GetLength()형태로 제공하니 얼마나 편합니까 .
출처:이상 데브피아
 
 
"이하" 파란 생각~
CString csTest = "사나이로 태어나서 할일은 사랑하기";
char* cTest = (LPSTR)(LPCTSTR)csTest;
AfxMessageBox(cTest);
 
즉, 위와 같이 무리한 형변환 보다는 CString의 Operator의 GetBuffer()을 사용해서 가지고오면 더욱 효율적입니다.
char* cTest;
CString csTest = "사나이로 태어나서 할일은 사랑하기";
cTest = csTest.GetBuffer(0);                //GetBuffer(0): csTest가 가지고 있는 문자열의 만큼 가지고 온다는 의미
AfxMessageBox(cTest);
 







Posted by SB패밀리

CString ↔ char 변환




1. CString을 char으로 변환
CString csTest;
csTest = "I Love You";
char* cTest = LPSTR(LPCTSTR(csTest));
 
2. char을 CString으로 변환
char cTest[10] = "I Love You";
CString csTest;
csTest.Format("%s", cTest);

출처 : http://blog.daum.net/sjdody/5693925



Posted by SB패밀리

MFC Active 생성





1. Workspace 생성

    MFC ActiveX control wizard를 선택.

2. Property 생성(메뉴 View > ClassWizard)

    1) ClassWizard의 Automation tab에서 선택
    2) Class name에서 Control class 선택(...Ctrl)
    3) (Add Property...) 버튼 클릭
    3) External name: ActiveX를 사용하는 프로그램에서 사용할 property name
    4) Type: property type
    5) Variable name: ActiveX 내부에서 사용할 property 변수명
    6) Notification function: property 값이 변경되면 실행되는 함수. 별로 사용하지 않는다.
    7) Implementation:
        - Member variable: 외부에서 ActiveX.propertyName = value 형태로 사용하는 방법
        - Get/Set methods: GetPropertyName(), SetPropertyName() 형태로 사용하는 방법

    ☞ 이렇게 하면,
        Conrol class에 해당 member 변수가 생성되는데, 변수명은
        Variable name에 설정된 이름으로 생성된다.

3. Method 생성

    1) ClassWizard의 Automation tab에서 선택
    2) Class name에서 Control class 선택(...Ctrl)
    3) (Add Method...) 버튼 클릭
    4) External name: ActiveX를 사용하는 프로그램에서 사용할 method 이름
    5) Internal name: ActiveX 내부에서 사용할 때 사용할 이름
    6) Return type: method를 호출했을 때, 결과로 넘겨줄 값의 type
    7) Parameter list: method에 넘겨줄 parameter와 그 type
    
    ☞ 이렇게 하면,
        Conrol class에 해당 method가 member함수로 생성되는데,
        함수 이름은 "Internal name"으로 생성된다.
        이 함수에 필요한 logic을 코딩하면 되며,
        ActiveX를 사용하는 프로그램에서 "External name"으로 설정된
        함수를 call하면, ActiveX에서는 "Internal name"으로 설정된
        함수가 실행된다.

4. Event 생성

    1) ClassWizard의 ActiveX Events tab 선택
    2) Class name: Control class 선택(...Ctrl)
    3) (Add Event...) 버튼 클릭
    4) External name: ActiveX를 사용하는 program에서 사용할 event name
    5) Internal name: ActiveX 내부에서 사용할 event name
    6) Parameter list: event도 하나의 함수다. 이 함수에 넘겨줄 parameter와
        그 type을 정의한다.

    ☞ 이렇게 하면,
        Conrol class의 Header file에 "Internal name"으로 설정된 void type의 함수가
        "AFX_EVENT(CSamAxCtrl)" event map으로 생성된다.
        ActiveX의 원하는 곳에서 이 함수를 call하면,
        ActiveX를 사용하는 프로그램에서 해당 event가 발생하게 된다.
    
5. 필요한 code 작성

    4번까지 하면, 기본적으로 ActiveX control이 작성된 것이다.
    여기에 필요한 logic을 작성한 다음 compile하면 ocx 파일이 생성된다.
    
6. CLSID 알아내기

    만들어진 ActiveX control을 웹에서 사용하기 위해서는 기본적으로 CLSID를 알아야 한다.
    이것은 VC++의 FileView에서 ".odl" 파일을 살펴보면 알 수 있다.
    ".odl" 파일의 맨 하단을 보면 다음과 같은 주석을 볼 수 있다.
    
         //  Class information for CExActiveX2Ctrl
    
    그리고, 그 밑에 아래와 같은 코드를 볼 수 있다.
    
        [ uuid(4AA8A54C-8F74-4F9F-8D3C-BD1079A73AD8),
          helpstring("ExActiveX2 Control"), control ]
    
    위 코드에서 "uuid"가 바로 CLSID 이다.

참고 : http://cafe.naver.com/swnara/145

Posted by SB패밀리

[개발/보안] Windows에서 프로그램을 실행할 때 "다음 계정으로 실행" 해결 방법


Microsoft Windows 2000 및 Microsoft Windows XP에서 현재 로그온한 사용자 이외의 사용자로 프로그램을 실행할 수 있습니다. 이렇게 하려면 Windows 2000에서는 RunAs 서비스를 실행하고 있어야 하고 Windows XP에서는 Secondary Logon 서비스를 실행하고 있어야 합니다. RunAs 서비스와 Secondary Logon 서비스는 이름이 다른 동일 서비스입니다. 이 문서에서는 Windows 2000 기반 컴퓨터나 Windows XP 기반 컴퓨터에서 다음 계정으로 실행 명령을 설정하고 사용하는 방법을 단계별로 설명합니다.

  1. 컴퓨터에 관리자로 로그온하거나 관리 권한이 있는 사용자로 로그온합니다.
  2. 내 컴퓨터 아이콘을 마우스 오른쪽 단추로 누른 다음 관리를 누릅니다.
  3. 컴퓨터 관리에서 서비스 및 응용 프로그램 노드를 확장한 다음 서비스를 누릅니다.
  4. 사용하는 운영 체제에 따라 다음 단계 중 하나를 수행합니다.
    • Windows 2000: 세부 정보 창에서 RunAs 서비스를 마우스 오른쪽 단추로 누른 다음 등록 정보를 누릅니다.
    • Windows XP: 세부 정보 창에서 Secondary Logon 서비스를 마우스 오른쪽 단추로 누른 다음 속성을 누릅니다.
  5. 등록 정보(Windows 2000) 또는 속성(Windows XP) 대화 상자에서 시작 유형을 자동으로 설정한 다음 시작을 누릅니다.
  6. 서비스가 시작되면 확인을 눌러 속성 대화 상자를 닫은 다음 컴퓨터 관리를 닫습니다.

다음 계정으로 실행 명령을 실행하는 데 필요한 서비스가 컴퓨터에서 실행됩니다.

 

윈도우즈 XP 에서 프로그램을 실행하려고 할때나 인터넷 익스플로러를 실행했을 때
"다음 계정으로 실행"이라는 창이 뜨는 경우가 있다.
인터넷 익스플로러의 경우 정확히 왜 이 창이 뜨는지 알 수가 없다. 세세하게 추적하는 수밖에...







이런 경우 개발자는 어떻게 해결해야할까? 내가 만든 프로그램이 실행을 하니 이런 창이 떡하니 화면에 나타난다면
난감하다.

ShellExecute() 함수를 사용해서 외부 프로그램을 실행할 때 이런 경우가 생긴다.
이런 경우 XP와 Vista 이상의 경우와 구분해서 ShellExecute()를 실행해줘야 한다.
Vista 이상에서는 관리자 권한으로 해서 실행해주고 XP에서는 그냥 일반적으로 실행해주면 된다.

Posted by SB패밀리

[개발/MFC] VC++/MFC API 팁



1. 특정 디렉토리 뒤지기
2. API를 이용하는 유니코드와 ANSI 문자열간의 변환 방법 
3. 윈도우 탐색기로부터의 Drag&Drop을 받으려면
4. 시스템의 모든 드라이브 알아내기
5. 레지스트리 읽기/쓰기



1. 특정 디렉토리 뒤지기 

지정한 디렉토리에 있는 모든 파일을 찾아내는 코드를 만들려면 어떻게 해야 합니까 ?

이 때 사용할 수 있는 API가 바로 FindFirstFile과 FindNextFile, FindClose라는 API들입니다. 사용 예제는 다음과 같습니다.

WIN32_FIND_DATA  findFileData; 
HANDLE hFileHandle;

// szDir에 뒤지고자 하는 디렉토리의 경로명을 준다. 예를 들면 "C:\\TEMP\\*.*" 
// 찾아진 파일의 속성은 findFileData의 dwFileAttributes를 살펴본다. 
hFileHandle = FindFirstFile(m_szDir, &findFileData);  
if (hFileHandle != INVALID_HANDLE_VALUE)  // 파일을 찾은 경우 

 // 찾은 파일의 이름은 cFileName 필드로 들어온다. 
 ... 
 // 다음 파일을 찾는다. 
 while(FindNextFile(hFileHandle, &findFileData)) { 
  ... 
 } 
 FindClose(hFileHandle); 
}


2. API를 이용하는 유니코드와 ANSI 문자열간의 변환 방법
 
API를 이용해서 유니코드와 ANSI 문자열간의 변환은 어떻게 수행합니까 ?

Visual C++에서 유니코드 문자열은 BSTR이란 타입으로 표시됩니다. 또 유니코드와 ANSI 문자열간의 변환을 위해서 윈도우 시스템에는 MultiByteToWideChar와 WideCharToMultiByte라는 API가 존재합니다. MFC에서의 BSTR 타입 변환방법이나 ATL로 하는 BSTR 타입 변환도 참고하시기 바랍니다.


ANSI 문자열에서 유니코드로의 변환 방법

// sTime이란 ANSI 문자열을 bstr이란 이름의 유니코드(BSTR 타입) 변수로 변환 
char sTime[] = "유니코드 변환 예제"; 
BSTR bstr;

// sTime을 유니코드로 변환하기에 앞서 먼저 그 길이를 알아야 한다. 
int nLen = MultiByteToWideChar(CP_ACP, 0, sTime, lstrlen(sTime), NULL, NULL); 
// 얻어낸 길이만큼 메모리를 할당한다. 
bstr = SysAllocStringLen(NULL, nLen); 
// 이제 변환을 수행한다. 
MultiByteToWideChar(CP_ACP, 0, sTime, lstrlen(sTime), bstr, nLen); 
// 필요없어지면 제거한다. 
SysFreeString(bstr);


유니코드에서 ANSI 문자열로의 변환 방법

// newVal이란 BSTR 타입에 있는 유니코드 문자열을 sTime이라는 ANSI 문자열로 변환 
char *sTime; 
int nLen = WideCharToMultiByte(CP_ACP, 0, newVal, -1, sTime, 0, NULL, NULL); 
sTime = malloc(nLen+1); 
WideCharToMultiByte(CP_ACP, 0, newVal, -1, sTime, 128, NULL, NULL); 
// 필요없으면 메모리를 제거한다. 
free(sTime);

유니코드 문자열을 UTF-8으로 변환하기

WideCharToMultiByte 함수를 호출할 때 첫 번째 인자로 CP_UTF8을 지정하면 된다.UTF-8은 유니코드의 인코딩 스킴 중의 하나로 쉽게 말하자면 문자열 스트림에서 0을 빼고 표현하는 방법이라고 볼 수 있다 


3. 윈도우 탐색기로부터의 Drag&Drop을 받으려면

윈도우 탐색기로부터 제가 만든 윈도우로의 drag&drop이 가능하게 하려면 어떻게 해야 합니까 ?

다음 순서를 따라서 프로그래밍하시면 됩니다.

프로그램의 초기화시에 DragAcceptFiles(hWnd, TRUE) 함수를 호출한다. 첫 번째 인자인 hWnd는 드롭의 타겟이 되는 윈도우의 핸들이다. 
탐색기로부터 파일이 드롭되는 순간에 WM_DROPFILES 메시지가 날라온다. 이를 처리한다.

case WM_DROPFILES : 

 POINT pt; 
 // 어느 위치에 드롭되었는지 그 항목을 알아낸다. 
 if (DragQueryPoint((HDROP)wParam, &pt)) 
 { 
  UINT i = 0; 
  // 모두 몇 개의 파일이 드롭되었는지 알아낸다. 
  // 만일 폴더가 드롭되었다면 폴더의 이름만 넘어온다. 
  UINT uCount = DragQueryFile((HDROP)wParam, 0xFFFFFFFF, NULL ,0);

  for(i = 0;i < uCount;i++) 
  { 
  // 드롭된 파일의 이름을 알아온다. 
  DragQueryFile((HDROP)wParam, i, buffer ,255); 
  // 드롭된 파일 이름을 출력해본다. 
  MessageBox(hWnd, buffer, "File Name", MB_OK); 
  } 
 } 
 // drag and drop 작업을 끝낸다. 
 DragFinish((HDROP)wParam); 
 break; 

Drag&drop을 더 사용할 필요가 없어지면 DragAcceptFiles를 호출한다. 
DragAcceptFiles(hWnd, FALSE); 


4. 시스템의 모든 드라이브 알아내기

현재 시스템에 붙어있는 모든 드라이브(네트웍 드라이브 포함)에 대한 정보를 알아내고 싶습니다.

GetLogicalDriveStrings로 시스템에 마운트되어있는 모든 드라이브 정보를 알아낸다. 두 번째 인자인 buffer로 드라이브 정보가 들어오는데 그 구조는 c:\,d:\과 같은 형식이며 리턴값으로 그 버퍼의 크기가 들어온다.

char buffer[256]; 
DWORD dwRet; 
LPSTR token;

dwRet = GetLogicalDriveStrings(256, buffer);

// 루프를 돌면서 드라이브별 정보를 알아낸다. 이 때는 GetVolumeInformation 함수를 이용한다.

token = buffer; // token이 지금 처리해야할 드라이브를 가리킨다. 
while (dwRet > 0) 

 DWORD FileSystemFlag; 
 char FileSystemName[64];

 strcpy(DriveString, token); 
 // VolumeName으로 드라이브에 대한 설명 문자열이 넘어온다. 
 if (GetVolumeInformation(token, VolumeName, 255, NULL, NULL, 
      &FileSystemFlag, FileSystemName, 63)) 
 { 
  // 원하는 작업을 수행한다. 
 } 
 dwRet -= (strlen(token)+1); 
 token = token + strlen(token)+1; // 다음 드라이브로 진행한다. 
}
 

5. 레지스트리 읽기/쓰기

API를 이용해서 레지스트리에 한 항목을 생성하거나 기존 항목의 값을 읽어들이려면 어떻게 해야합니까 ?

레지스트리 관련 API를 사용하려면 winreg.h라는 헤더 파일을 소스에 포함해야 합니다. 레지스트리에 키를 생성하는 방법과 레지스트리에 존재하는 키의 값을 읽는 방법을 차례로 살펴보겠습니다.


레지스트리 키 생성 예제

// 예를 들어 HKEY_LOCAL_MACHINE밑의 System\CurrentControlSet\Services\GenPort라는 키를 
// 생성하고 거기에 DWORD 타입의 값으로 Type을 만들고 문자열 타입의 값으로 Group 
// 을 만들어 본다. 
#include "winreg.h" 
LONG error = 0; 
HKEY hKey; 
DWORD dwDisp, dwData; 
char lpData[] = "Write this down";

// 먼저 만들려는 키가 이미 존재하는 것인지 살혀본다. 
error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\GenPort", 
                        0, KEY_ALL_ACCESS, &hKey);

if (error != ERROR_SUCCESS) // 없다면 새로 생성한다. 

 // 키를 생성한다. 
 error = RegCreateKeyEx(HKEY_LOCAL_MACHINE, 
  "System\\CurrentControlSet\\Services\\GenPort", 0, "REG_BINARY", 
         REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hKey, &dwDisp); 
        // 위의 키 밑에 Type이란 DWORD 타입의 값을 만들고 1로 초기화 
 dwData = 0x1; 
 error = RegSetValueEx( hKey, "Type", 0, REG_DWORD,&dwData,4); 
        // 위의 키 밑에 Group이란 문자열 타입의 값을 만들고 lpData의 값으로 초기화 
 error = RegSetValueEx( hKey, "Group", 0, REG_SZ, lpData, strlen(lpData));

        // 키를 닫는다. 
 RegCloseKey(hKey); 
}

기존의 레지스트리 키에서 값 읽기

// HKEY_CURRENT_USER\Software\Netscape\Netscape Navigator\Main 밑의 Install Directory 
// 값의 문자열 값을 읽어들인다. 
DWORD dwType, cbData; 
HKEY hSubKey; 
long lRet; 
char pszString[255];

// 키를 오픈한다. 
if ((lRet = RegOpenKeyEx(HKEY_CURRENT_USER, 
                "Software\\Netscape\\Netscape Navigator\\Main", 
  0, KEY_READ | KEY_QUERY_VALUE , &hSubKey)) == ERROR_SUCCESS) 

 cbData = 255; // 문자열 값을 읽어올 데이터의 크기를 준다. 
 if ((lRet = RegQueryValueEx(hSubKey, "Install Directory", 
  NULL, &dwType, pszString, &cbData)) == ERROR_SUCCESS) 
 { 
  // 제대로 읽힌 경우 
 } 
 else 
 { 
  // 에러가 발생한 경우 
 } 
 RegCloseKey(hSubKey); 
}

레지스트리 키 삭제하기 
- RegDeleteKey 함수를 사용한다.

Posted by SB패밀리

Thread, Process ID & Handle 



윈도우즈용 응용프로그램, ActiveX, DLL, Windows Service 등을 만들기 위해서 알아두어야 할 기본적인 지식들



출처 : http://radrome.springnote.com/pages/2213794

 윈도우, 프로세스, 모듈
    - 핸들, ID, 파일이름

    파일이름 만으로 전체 경로 얻기 GetFullPathName(  sFileName,   _MAX_PATH,  sFullFull,  0);
                                        -> 문제 : 현재 경로에 파일름만 붙인다.
                        GetFullPath()(만듬) : 파일일 현재 실행된 파일의 경로에 있는 검사해서 붙인다.

 
* 윈도우

    윈도 Instance : (SDK) GetWindowLong(hWndCur, GWL_HINSTANCE),   (MFC)HINSTANCE AfxGetInstanceHandle();
    현재 Window Handle    : GetCurrentWindowHandle(만듬)   
    Process Handle (ID) -> Window Handle : HWND GetWindowHandleFromProcessId(DWORD dwProcId) (만듬)   
* 프로세스

    현재 Process Handle : HANDLE GetCurrentProcess(VOID);
    현재 Process ID        : DWORD GetCurrentProcessId(VOID);
    프로세스(모듈) 파일 이름  : GetModuleBaseName(hProc, 0, sNameOnly, _MAX_PATH);//이름만
                      GetModuleFileName(0, sFullPath, _MAX_PATH);//전체경로
    Win Handle -> Process Handle : GetWindowThreadProcessId

 

   OpenProcess, CreateProcess
    Process ID -> Process Handle : GetProcessId() , API인데 MSDN 설명이 안나옴

    GetCurrentProcessorNumber() ??
    GetCurrentActCtx()??
* 모듈

    현재 Module Handle    : GetCurrentModule(만듬)
    파일이름 -> 모듈핸들 : GetModuleHandle();//현재 프로세스에서만 작동
                        특정프로세스 안에 있는 모듈 핸들 GetModuleHandle()(만듬), 외부 프로세스에서 작동
    모듈ID -> 모듈 핸들 :
* 쓰레드

    현재 쓰레드 핸들    : GetCurrentThread()

    현재 쓰레드 ID        : GetCurrentThreadId()



Posted by SB패밀리

[개발/VC] 레지스트리 키 열기, 닫기, 목록 가져오기, 키 값 가져오기 


레지스트리 키 열기, 닫기
키 목록 가져오기,
키에 해당하는 값 가져오기(GetText, GetDword 외 필요하시면 추가하시면 됩니다.)
키하위의 값목록 가져오기.

이와 같은 동작을 하는 함수만 아래 나열.
 
typedef struct REGVALUE_T
{
    enum
    {
        TYPE_NONE,
        TYPE_DWORD,
        TYPE_SZ
    }type;
    string key;
    union
    {
        DWORD val_dword;
        char *val_sz;
    }value;
}RegValue, *PRegValue;
 
typedef list RegValueList;
 
 
HKEY RegCtrl::OpenKey(string keyName)
{
    HKEY hKey = NULL;
    string retval_;
    LONG lretval_;
    string rValueName_;
 
    lretval_ = RegOpenKeyEx( HKEY_LOCAL_MACHINE, keyName.c_str(), 0, KEY_ALL_ACCESS, &hKey );
    if(lretval_ != ERROR_SUCCESS)
    {
        return NULL;
    }
 
    return hKey;
}
 
void RegCtrl::CloseKey(HKEY hKey)
{
    // TODO: Add your specialized code here.
    LONG lretval_ = RegCloseKey(hKey);
    if(lretval_ != ERROR_SUCCESS)
    {
    }
}
 
 list RegCtrl::GetKeyList(HKEY hKey)
{
    list retval_;
    CHAR     achKey[MAX_KEY_LENGTH];    // buffer for subkey name
    DWORD   cbName;                     // size of name string 
    CHAR     achClass[MAX_PATH] = "";   // buffer for class name 
    DWORD   cchClassName = MAX_PATH;    // size of class string 
    DWORD   cSubKeys=0;                 // number of subkeys 
    DWORD   cbMaxSubKey;                // longest subkey size 
    DWORD   cchMaxClass;                // longest class string 
    DWORD   cValues;                    // number of values for key 
    DWORD   cchMaxValue;                // longest value name 
    DWORD   cbMaxValueData;             // longest value data 
    DWORD   cbSecurityDescriptor;       // size of security descriptor 
    FILETIME ftLastWriteTime;           // last write time 
 
    DWORD i, lretval_; 
 
    DWORD cchValue = MAX_VALUE_NAME; 
 
    // Get the class name and the value count. 
    lretval_ = RegQueryInfoKey(
        hKey,   // key handle 
        achClass,               // buffer for class name 
        &cchClassName,          // size of class string 
        NULL,                   // reserved 
        &cSubKeys,              // number of subkeys 
        &cbMaxSubKey,           // longest subkey size 
        &cchMaxClass,           // longest class string 
        &cValues,               // number of values for this key 
        &cchMaxValue,           // longest value name 
        &cbMaxValueData,        // longest value data 
        &cbSecurityDescriptor,  // security descriptor 
        &ftLastWriteTime);      // last write time 
 
    // Enumerate the subkeys, until RegEnumKeyEx fails.
    
    if (cSubKeys)
    {
//      printf( "Number of subkeys: %d\n", cSubKeys);
        for (i=0; i
        { 
            cbName = MAX_KEY_LENGTH;
            lretval_ = RegEnumKeyEx(hKey,
                                    i,
                                    achKey, 
                                    &cbName, 
                                    NULL, 
                                    NULL, 
                                    NULL, 
                                    &ftLastWriteTime); 
            if (lretval_ == ERROR_SUCCESS) 
            {
                retval_.push_back( achKey);
            }
        }
    } 
    return retval_;
}
 
string RegCtrl::GetText(HKEY hKey, string name)
{
    string retval_;
    DWORD size_ = 0;
    LONG lretval_;
 
    retval_.resize(256);
    size_ = retval_.size();
 
    lretval_ = RegQueryValueEx( hKey, name.c_str(), NULL, NULL, (LPBYTE)((LPCTSTR)retval_.c_str()), &size_);
    if(lretval_ == ERROR_MORE_DATA)
    {
        retval_.resize(retval_.size() + size_);
        size_ = retval_.size();
        lretval_ = RegQueryValueEx(hKey, name.c_str(), 0, NULL, (LPBYTE)((LPCTSTR)retval_.c_str()), &size_);
    }
    else if(lretval_ != ERROR_SUCCESS)
    {
        retval_.resize(0);
    }
 
    return retval_;
}
 
DWORD RegCtrl::GetDword(HKEY hKey, string name)
{
    DWORD retval_ = 0;
    DWORD size_ = 0;
    LONG lretval_;
 
    size_ = sizeof(retval_);
 
    lretval_ = RegQueryValueEx( hKey, name.c_str(), NULL, NULL, (LPBYTE)&retval_, &size_);
    if(lretval_ != ERROR_SUCCESS)
    {
        return 0;
    }
    
    return retval_;
}
 
RegValueList RegCtrl::GetValueList(HKEY hKey)
{
    RegValueList retval_;
//  CHAR    achKey[MAX_KEY_LENGTH]; // buffer for subkey name
//  DWORD   cbName;                     // size of name string 
    CHAR    achClass[MAX_PATH] = "";    // buffer for class name 
    DWORD   cchClassName = MAX_PATH;    // size of class string 
    DWORD   cSubKeys=0;                 // number of subkeys 
    DWORD   cbMaxSubKey;                // longest subkey size 
    DWORD   cchMaxClass;                // longest class string 
    DWORD   cValues;                    // number of values for key 
    DWORD   cchMaxValue;                // longest value name 
    DWORD   cbMaxValueData;             // longest value data 
    DWORD   cbSecurityDescriptor;       // size of security descriptor 
    DWORD   cType;                      // type of value
    FILETIME ftLastWriteTime;           // last write time 
 
    DWORD i, lretval_; 
 
    DWORD cchValue = MAX_VALUE_NAME; 
 
    // Get the class name and the value count. 
    lretval_ = RegQueryInfoKey(
        hKey,   // key handle 
        achClass,               // buffer for class name 
        &cchClassName,          // size of class string 
        NULL,                   // reserved 
        &cSubKeys,              // number of subkeys 
        &cbMaxSubKey,           // longest subkey size 
        &cchMaxClass,           // longest class string 
        &cValues,               // number of values for this key 
        &cchMaxValue,           // longest value name 
        &cbMaxValueData,        // longest value data 
        &cbSecurityDescriptor,  // security descriptor 
        &ftLastWriteTime);      // last write time 
 
    // Enumerate the key values. 
    CHAR  achValue[MAX_VALUE_NAME]; 
    if (cValues) 
    {
//      printf( "\nNumber of values: %d\n", cValues);
        for (i=0, lretval_=ERROR_SUCCESS; i
        { 
            cchValue = MAX_VALUE_NAME; 
            achValue[0] = '\0'; 
            lretval_ = RegEnumValue(hKey, i, 
                achValue, 
                &cchValue, 
                NULL, 
                &cType,
                NULL,
                NULL);
 
            if (lretval_ == ERROR_SUCCESS ) 
            {
                RegValue value;
                value.key = achValue;
                if(cType == REG_DWORD)
                {
                    value.type = RegValue::TYPE_DWORD;
                    value.value.val_dword = YMRegCtrl::GetDword(hKey, value.key);
                }
                else if(cType == REG_SZ)
                {
                    value.type = RegValue::TYPE_SZ;
                    string tmp_ = YMRegCtrl::GetText(hKey, value.key);
                    value.value.val_sz = new char[tmp_.length()+2];
                    strcpy(value.value.val_sz, tmp_.c_str());
                }
                else
                {
                    value.type = RegValue::TYPE_NONE;
                }
                retval_.insert(retval_.end(), value);
//              printf("(%d) %s\n", i+1, achValue); 
            } 
        }
    }
 
    return retval_;
}

Posted by SB패밀리

내가 특정 프로그램명을 알고 있을 때 
그 특정 프로그램의 윈도우 핸들을 구할 수 있다.
그러면, 핸들에서 프로세스 ID를 구할 수 있게 된다.

그 다음 순서는 분명하다.
프로세스를 강제로 종료시키는 것이다.
그럼 아래 소스를 살펴보자.


HWND hOsk=::FindWindow(NULL, "SBRICH");
 if(hOsk) 
 {
  CWnd* p = CWnd::FromHandle(hOsk);
  CString sT;
  p->GetWindowTextA(sT);
  DWORD pid2;
  DWORD  pid = GetWindowThreadProcessId(hOsk, &pid2); // 바로서치 핸들로 프로세스 id를 구한다.

  HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid2); 
 
      if(hProcess)
      {
         if(TerminateProcess(hProcess, 0))
         {
            unsigned long nCode; //프로세스 종료 상태 
            GetExitCodeProcess(hProcess, &nCode);
         }

         CloseHandle(hProcess); 
      }

  AfxMessageBox(sT);
 }

Posted by SB패밀리

[개발/MFC] 날짜계산, 시간계산 해보자



MFC에서 현재 시간을 기준으로 시간계산을 하는 방법을 알아보자.

아래의 예제만 알면... 더하고 빼고 차이를 계산하는 건 문제가 아니다.

먼저 현재 날짜와 시간을 제대로 얻어야 한다.


처음 사용한다면 변수에 날짜와 시간을 표시하는 과정을 갖고 확인하는 습관을 들이자.


그럼 아래에 예제가 있다.

오늘로부터 3일 뒤의 날짜를 알고 싶다.


CString s;


 CTime ctTime = CTime::GetCurrentTime();


 s.Format("%04d.%02d.%02d", ctTime.GetYear(), ctTime.GetMonth(), ctTime.GetDay());


 CTimeSpan tsAddTime(3, 0, 0, 0); 


 ctTime += tsAddTime; // 날짜 더하기 


 s.Format("%04d.%02d.%02d", ctTime.GetYear(), ctTime.GetMonth(), ctTime.GetDay());


 


MFC에서 해보니 잘 나온다

Posted by SB패밀리

윈도우즈에서 실행중인 프로세스를 강제 종료시키자.
내가 사용하는 방법도 있지만 아래 소스가 잘 정리되어 있어서 그대로 스크랩했다.



출처 : http://koronaii.tistory.com/241

BOOL CGomControl::ProcessKill(CString strProcessName)                                                                       
{                                                                                                                                                           
   HANDLE hProcessSnap = NULL;                                                                                                          
   BOOL bRet = FALSE;                                                                                                                          
   PROCESSENTRY32 pe32 = {0};                                                                                                          
                                                                                                                                                           
   hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);                                              
   if (hProcessSnap == (HANDLE)-1)                                                                                                       
       return false;                                                                                                                                  
   pe32.dwSize = sizeof(PROCESSENTRY32);                                                                                          
                                                                                                                                                           
   //프로세스가 메모리상에 있으면 첫번째 프로세스를 얻는다                                                                        
   if (Process32First(hProcessSnap, &pe32))                                                                                            
   {                                                                                                                                                      
       BOOL bCurrent = FALSE;                                                                                                               
       MODULEENTRY32 me32 = {0};                                                                                                       
                                                                                                                                                           
       do {                                                                                                                                             
           bCurrent = GetProcessModule(pe32.th32ProcessID,strProcessName);                                            
           if(bCurrent) {                                                                                                                            
               HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);           
               if(hProcess) {                                                                                                                        
                   if(TerminateProcess(hProcess, 0)) {                                                                                    
                       unsigned long nCode; //프로세스 종료 상태                                                                       
                       GetExitCodeProcess(hProcess, &nCode);                                                                         
                   }                                                                                                                                      
                   CloseHandle(hProcess);                                                                                                     
               }                                                                                                                                          
           }                                                                                                                                              
       }                                                                                                                                                  
       //다음 프로세스의 정보를 구하여 있으면 루프를 돈다.                                                                           
       while (Process32Next(hProcessSnap, &pe32));                                                                                 
   }                                                                                                                                                      
                                                                                                                                                           
   CloseHandle (hProcessSnap);                                                                                                             
   return true;                                                                                                                                       
}                                                                                                                                                           
  
                                                                                                                                                         
BOOL CGomControl::GetProcessModule(DWORD dwPID, CString sProcessName)                                        
{                                                                                                                                                           
   HANDLE hModuleSnap = NULL;                                                                                                           
   MODULEENTRY32 me32 = {0};                                                                                                           
                                                                                                                                                           
   hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);                                          
   if(hModuleSnap == (HANDLE)-1)                                                                                                         
       return (FALSE);                                                                                                                             
   me32.dwSize = sizeof(MODULEENTRY32);                                                                                           
                                                                                                                                                           
   //해당 프로세스의 모듈리스트를 루프로 돌려서 프로세스이름과 동일하면                                                     
   //true를 리턴한다.                                                                                                                              
   if(Module32First(hModuleSnap, &me32)) {                                                                                           
       do {                                                                                                                                             
           if(me32.szModule == sProcessName)                                                                                          
           {                                                                                                                                              
               CloseHandle (hModuleSnap);                                                                                                  
               return true;                                                                                                                           
           }                                                                                                                                              
       }                                                                                                                                                  
                                                                                                                                                           
       while(Module32Next(hModuleSnap, &me32));                                                                                   
   }                                                                                                                                                      
                                                                                                                                                           
   CloseHandle (hModuleSnap);                                                                                                              
   return false;                                                                                                                                      
}                                                                                                                                                           
                                                                                                                                                           
                                                                                                                                                           
                                                                                                                                                           
bool CGomControl::GomClose(){                                                                                                           
   return ProcessKill(_T("GOM.exe"));//실제 죽이는 구문      

Posted by SB패밀리

[개발/MFC] 유휴 루프 처리



Visual Studio .NET 2003

많은 응용 프로그램은 "백그라운드에서" 처리 시간이 긴 작업을 수행합니다. 경우에 따라 이러한 작업에 다중 스레딩을 사용하면 성능을 향상시킬 수 있습니다. 스레드로 인해 개발 과정에 불필요한 오버헤드가 발생하기 때문에 MFC가 OnIdle 함수에서 수행하는 유휴 시간 작업과 같은 단순 작업에는 적당하지 않습니다. 따라서 이 문서에서는 유휴 처리를 중심으로 설명합니다. 다중 스레딩에 대한 자세한 내용은 다중 스레딩 항목을 참조하십시오.

일 부 백그라운드 처리는 사용자가 응용 프로그램과 상호 작용을 하지 않는 동안에 적절하게 수행됩니다. Microsoft Windows 운영 체제용으로 개발된 응용 프로그램은 시간이 많이 걸리는 프로세스를 여러 개의 작은 조각으로 나눠 유휴 시간에 수행할 수 있습니다. 각 조각을 수행한 후에 응용 프로그램은 PeekMessage 루프를 사용하여 실행 제어를 Windows로 돌려줍니다.

다음은 응용 프로그램에서 유휴 처리를 수행하는 두 가지 방법에 대한 설명입니다.

  • MFC의 주 메시지 루프에서 PeekMessage 사용
  • 응용 프로그램의 다른 곳에서 다른 PeekMessage 루프 포함

MFC 메시지 루프에서 PeekMessage 사용

MFC로 개발한 응용 프로그램에서 CWinThread 클래스에 있는 주 메시지 루프는 PeekMessage Win32 API를 호출하는 메시지 루프를 포함합니다. 또한, 이 루프는 메시지 사이사이에 CWinThread의 OnIdle 멤버 함수도 호출합니다. 응용 프로그램은 OnIdle 함수를 재정의하여 유휴 시간에 메시지를 처리할 수 있습니다.

참고   RunOnIdle 및 다른 일부 멤버 함수는 이제 CWinApp 클래스가 아닌 CWinThread 클래스의 멤버입니다. CWinAppCWinThread에서 파생됩니다.

유휴 처리에 대한 자세한 내용은 MFC Reference의 OnIdle을 참조하십시오.

응용 프로그램의 다른 곳에서 PeekMessage 포함

응용 프로그램에서 유휴 처리를 수행하는 다른 방법은 함수 중 하나에 메시지 루프를 포함하는 것입니다. 이 메시지 루프는CWinThread::Run에 서 볼 수 있는 MFC의 주 메시지 루프와 매우 유사합니다. 이것은 MFC로 개발한 응용 프로그램에 있는 이러한 루프가 주 메시지 루프와 대부분 같은 기능을 수행한다는 의미입니다. 다음 코드에서는 MFC와 호환되는 메시지 루프를 작성하는 방법을 보여 줍니다.

while ( bDoingBackgroundProcessing ) 
{ 
    MSG msg;
    while ( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) 
    { 
        if ( !PumpMessage( ) ) 
        { 
            bDoingBackgroundProcessing = FALSE; 
            ::PostQuitMessage( ); 
            break; 
        } 
    } 
    // let MFC do its idle processing
    LONG lIdle = 0;
    while ( AfxGetApp()->OnIdle(lIdle++ ) )
        ;  
    // Perform some background processing here 
    // using another call to OnIdle
}

함수에 포함된 이 코드는 수행할 유휴 처리가 있는 한 루프를 이룹니다. 이 루프 안에서 중첩된 루프는 PeekMessage를 반복 호출합니다. 호출 결과로 0이 아닌 값이 반환되는 한 이 루프는 CWinThread::PumpMessage를 호출하여 일반 메시지 변환과 디스패칭을 수행합니다. 문서에 PumpMessage가 설명되어 있지는 않지만 Visual C++가 설치된 \atlmfc\src\mfc 디렉터리에서 ThrdCore.Cpp 파일의 소스 코드를 직접 확인해 볼 수 있습니다.

일단 내부 루프가 끝나면 외부 루프가 OnIdle을 하나 이상 호출하여 유휴 처리를 수행합니다. 첫째 호출은 MFC를 위한 것입니다 OnIdle을 추가로 호출하여 사용자 지정 백그라운드 작업을 수행할 수 있습니다.

유휴 처리에 대한 자세한 내용은 MFC 라이브러리 참조의 OnIdle을 참조하십시오

출처 : http://msdn.microsoft.com/ko-kr/library/cc485601%28v=vs.71%29.aspx

Posted by SB패밀리

[개발/MFC] UTF8로 파일저장하기 


CString strFilePath = dlg.GetPathName();

 

// UTF8로 컨버팅
int nAllocLen = WideCharToMultiByte (CP_UTF8, 0, strSaveData, -1, NULL, 0, NULL, NULL);
CHAR * pBuffer = new CHAR [nAllocLen + 1];
memset (pBuffer, 0, nAllocLen);
WideCharToMultiByte (CP_UTF8, 0, strSaveData, -1, pBuffer, nAllocLen + 1, NULL, NULL);

 

// 파일로 저장
CFile file;
file.Open (strFilePath, CFile::modeCreate | CFile::modeWrite);
file.Write (pBuffer, nAllocLen);

 

// 메모리 해제
delete [] pBuffer;

Posted by SB패밀리

[MFC] WM_TIMER 예제


// Message Map
BEGIN_MESSAGE_MAP(CDlgDlg, CDialog)
    ...
    ON_WM_TIMER()
END_MESSAGE_MAP()

...

// Timer ID constants.
const UINT ID_TIMER_ONE  = 0x1001;
const UINT ID_TIMER_TWO = 0x1000;

// Start the timers.
void CDlgDlg::StartTimer()
{
    // Set timer for Minutes.
    SetTimer( ID_TIMER_ONE, 60 * 1000, 0 );

    // Set timer for Seconds.
    SetTimer( ID_TIMER_TWO, 1000, 0 );
}

// Stop the timers.
void CDlgDlg::StopTimer()
{
    // Stop both timers.
    KillTimer( ID_TIMER_ONE  );
    KillTimer( ID_TIMER_TWO );
}

// Timer Handler.
void CDlgDlg::OnTimer( UINT nIDEvent )
{
    // Per minute timer ticked.
    if( nIDEvent == ID_TIMER_ONE )
    {
        // Do your minute based tasks here.
    }

    // Per minute timer ticked.
    if( nIDEvent == ID_TIMER_TWO )
    {
        // Do your seconds based tasks here.
    }
}

 

위의 방법외에도 다른 방법이 있다.

UINT SetTimer(
   UINT nIDEvent,
   UINT 
nElapse,
   void ( CALLBACK* 
lpfnTimer )(HWND, UINT, UINT, DWORD) = NULL 
) throw();

void CALLBACK TimerProc(HWND hWnd, UINT nIDEvent, UINT nElapse, DWORD dwTime)
{
    CWnd *pWnd = AfxGetMainWnd();

    CTestProgDlg *dlg = (CTestProgDlg *)pWnd;

    dlg->ShowWindow(SW_SHOW);
}

Posted by SB패밀리

[개발/MFC] Sleep()함수 대신 프로그램 딜레이 시키기 

개발을 하다가 보면... 어떤 조건이 true가 될 때까지 기다려야 할 때가 있다.
그렇게 하려면 loop를 사용해야한다. 
그리고 대기함수인 Sleep() 함수를 사용하게 되는 경우가 생기는데
이 함수를 사용하면. 모든 메세지 처리가 중단되기 때문에 
프로그램 응답 없음과 같은 애매하고 난감한 사항에 처하게 된다.
그래서 이 Sleep()이라는 함수 대신에
프로세스나 쓰레드에서 사용되는 메세지는 처리되면서 특정조건이 
만족할 때까지 기다릴 수 있는 함수가 필요하다.

대기시간 동안 메세지큐에서 메세지를 확인하여 처리하면서 
기다리게 해준다.

/////////////////////////////////////////////////////////////////
// 수행 대기 delay 함수(instead sleep function)
/////////////////////////////////////////////////////////////////
void CBaConApp::Wait(DWORD dwMillisecond)
{
 MSG msg;
 DWORD dwStart;
 dwStart = GetTickCount();

 while(GetTickCount() - dwStart < dwMillisecond)
 {
  while(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
 }
}

Posted by SB패밀리

[개발/MFC] "다음 계정으로 실행" 나오지 않게 만들기


VS2008이나 다른 개발 툴에서 개발을 할 때

UAC 실행 수준을 아래와 같이 설정해 주어야 한다.




개발을 할 때 외부프로그램 실행에 대해서


Windows XP 버전과 Vista를 포함한 이상 버전에 대해서 처리도 필요하다.

"runas" 라는 옵션을 사용하면 처리가 된다.

그렇지 않으면 아래와 같은 화면이 나타난다.






Posted by SB패밀리

1. DC얻기

CClientDC dc(this);


2. Client 영역 구하기

GetClientRect(&rect);

WM_SIZE 메시지발생후 cx,cy 사용


3. 문자열 사각형안에 그리기

pDC->DrawText(문자열,사각형,Style);

Style : DT_BOTTOM - 문자열을 사각형 맨아래줄에배열 반드시DT_SINGLELINE과 함께사용

DT_CENTER - 문자열을 가로중앙에 배치

DT_VCENTER - 문자열을 세로중앙에 배치

DT_LEFT,RIGHT - 문자열을 좌,우로 배치

DT_SINGLELINE - 문자열을 한줄로만 쓴다


4. Brush 사용법

CBrush brushname(RGB(red,green,blue)); //브러쉬 생성

//이전Brush 저장, 새로운 Brush 선택

CBrush *oldBrush=pDC->SelectObject(&brushname);

pDC->SelectObject(oldBrush); //원래의 브러쉬로 반환


5. Pen사용법

CPen pen(Pen Style,RGB(red,green,blue)); //브러쉬생성

//Style: PS_SOLID,PS_DASH,PS_DOT,PS_DASHDOT,PS_GEOMETRIC,PS_COSMETRIC

- 펜종류

PS_ENDCAP_ROUND,PS_ENDCAP_SQUARE - 펜끝을 둥글게,각지게 설정

CPen *oldPen=pDC->SelectObject(&pen); //이전Pen저장, 새로운 Pen설정

pDC->SelectObject(oldPen); //펜반환


6. 화면다시그리기

View Class에서 - Invalidate(TRUE) : 화면을 지우고다시그린다

Invalidate(FALSE) : 화면을 덮어씌운다

UpdateAllViews(NULL); // Doc Class에서 View 의 OnDraw 호출

RedrawWindow();


7. 메시지,함수 수동으로 넣기 (EX)버튼클릭함수넣기

헤더파일의 AFX_MSG_MAP 부분에 함수를 정의

// .cpp파일의 AFX_MSG 부분에 메시지를 추가한다

EX) afx_msg void funcName();

// ID 등록: View 메뉴의 Resource Symbol 에 들어가서 메뉴 ID 를 등록해준다..

EX) ON_BN_CLICKED(ID_NAME,funcName).

// .cpp파일의 맨아래에서 함수를 정의한다

EX) void CClass::funcName() { ... }


8. 마우스커서 바꾸기

리소스탭에서 커서를 그리고 저장한뒤 ID값은 준다음

SetCapture(); //커서의입력을 클라이언트영역을 벗어나더라도 받아낸다

SetCursor(AfxGetApp()->LoadCursor(nIDResource));

//APP클래스의 LoadCursor View의 SetCursor 사용

ReleaseCapture(); //SetCursor()상태를 해제한다


9. 색상표 사용하기

CColorDialog dlg;

if(dlg.DoModal()==IDOK) //Dialog 를 띄운후 OK버튼을누르면 실행할부분

MemberFunc: GetColor() //선택된 색상을 받아온다 return 형은 COLORREF 형


10. 팝업메뉴 만들기

CMenu menu; //메뉴 객체생성

CMenu *pmenu; //메뉴 포인터생성

menu.LoadMenu(IDR_MAINFRAME); //메뉴를 불러온다

pmenu=menu.GetSubMenu(3); //메뉴의 3번째 메뉴를 가져온다

menu.CheckMenuItem(ID_MENU,m_kind==ID_MENU ? MF_CHECKED : MF_UNCHECKED); //메뉴 체크하기 (메뉴 ID, ID 체크조건)

pmenu->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this) //(TMP_Style,x좌표,y좌표,hWnd) 메뉴 띄우기


*주의사항*

[안내]태그제한으로등록되지않습니다-OnContextMenu(CWnd* pWnd, CPoint point) //여기서 point 는 스크린 기준이고,

OnRButtonDown(UINT nFlags, CPoint point) //여기서 point 는 클라이언트 기준이다!


11. 클라이언트 포인터를 스크린 포인터로 변경

ClientToScreen(&point);


12. 그림판기능

if(m_flag==FALSE) return; //m_falg=그리기 기능 참,거짓설정 그리기 아니면 빠져나간다

CClientDC dc(this);

CPen myPen(PS_SOLID,m_width,m_color);

CPen *pOldPen=dc.SelectObject(&myPen);

switch(m_shape)

{

case ID_FREELINE: //자유선그리기

dc.MoveTo(m_oldpt.x,m_oldpt.y); //지난포인터부터

dc.LineTo(point.x,point.y); //새포인터까지 그린다

break;

case ID_RECT: //사각형그리기

dc.SetROP2(R2_NOTXORPEN);

dc.Rectangle(m_spt.x,m_spt.y,m_oldpt.x,m_oldpt.y); //지워지는 효과

dc.Rectangle(m_spt.x,m_spt.y,point.x,point.y); //그려지는 효과

break;

case ID_ELLIPSE: //원그리기

dc.SetROP2(R2_NOTXORPEN);

dc.Ellipse(m_spt.x,m_spt.y,m_oldpt.x,m_oldpt.y); //지워지는 효과

dc.Ellipse(m_spt.x,m_spt.y,point.x,point.y); //그려지는 효과

break;

case ID_LINE: //선그리기

dc.SetROP2(R2_NOTXORPEN);

dc.MoveTo(m_spt.x,m_spt.y); //시작점부터

dc.LineTo(m_oldpt.x,m_oldpt.y); //지난점까지 그은선을 지운다

dc.MoveTo(m_spt.x,m_spt.y); //시작점부터

dc.LineTo(point.x,point.y); //새로운점까지 그린다

break;

}

m_oldpt=point; //바로이전값 보관

dc.SelectObject(pOldPen); //펜 반환


13. MessageBox

AfxMessageBox()->전역함수를 이용하영 메세지 박스를 출력한다. //어디서든지 사용할수 잇다

int CWnd::MessageBox("메세지","창제목","아이콘|버튼(상수값)"); //View클래스에서 사용한다

아이콘 상수값 MB_IC[안내]태그제한으로등록되지않습니다 - xxONERROR,

MB_ICONWARNING, MB_ICONQUESTION,MB_ICONINFOMATION

MB_SYSTEMMODAL //시스템모달 대화창 닫기전에 다른작업 못함

MB_APPLMODAL //응용모달

버튼 상수값 MB_OK, MB_OKCANCEL, MB_YESNO


14. OS 컨트롤

ExitWindowEx(EWX_SHUTDOWN,NULL); //Shut Down

ExitWindowsEx(EWX_FORCE,0); //강제종료

ExitWindowsEx(EWX_LOGOFF,0); //로그오프

ExitWindowsEx(EWX_POWEROFF,0); //Shut Down -> Turn Off

ExitWindowsEx(EWX_REBOOT); //Shut Down -> Reboot


15. DialogBox 메시지 교환

UpdateData(FALSE); // 컨트롤에 멤버변수의 내용을 표시해준다

UpdateData(TRUE); // 컨트롤 내용을 다이얼로그 클래스의 멤버변수로 저장


16. 자료변환

atoi,itoa - int <=> ASCII(char) 변환

str.Format(" %d %d",x,y); // int형을 문자열로 변환

atol,ltoa - ASCII <=> long 변환

atof - ACSII => float 변환

fcvt,gcvt - 실수를 text로 변환

LPtoDP, DPtoLP - 장치좌표 <=> 논리좌표 변환


17. CEdit Class 사용하기

CEdit e_str.SetSel(int StartChae, int EndChar); //처음문자부터 마지막까지 블록 지정

CEdit e_str.GetSel(int SChar,int EChar); //블럭 지정한 처음문자와 마지막문자 받기

CString str=m_str.Mid(SChar,EChar-SChar); //블럭지정한 부분을 가져온다


18. 컨트롤과 자료교환

SetDlgItemText(컨트롤 ID,문자열) //컨트롤에 문자열을 넣는다

GetDlgItemText(컨트롤 ID,문자열) //컨트롤의 내용을 문자열에 넣는다

GetDlgItem(컨트롤 ID); //컨트롤의 주소를 가져온다


19. 상태바조작

CMainFrame 생성자 위에

static UINT indicators[] = //이안에 새로운 ID를 넣고 그 ID의 갱신핸들러를 만든다음 코딩

pCmdUI->SetText("표시할내용“);


20. 수동으로 Bitmap 컨트롤 사용하기

CStatic bitmap; //bitmap 컨트롤변수

bitmap.SetBitmap(CBitmap m_bitmap); //컨트롤에 비트맵지정

GetDlgItem(IDC_BITMAP)->ShowWindow(SW_SHOW,HIDE); // 그림을 보이거나 숨긴다.

21. 응용프로그램 실행하기

WinExec("프로그램경로“,SW_SHOW,HIDE); //응용프로그램실행,경로는 \\로 구분한다


22. Bitmap 사용하기

CBitmap bitmap.LoadBitmap(IDC_BITMAP); //비트맵객체에 비트맵지정

CDC memDC; //그림그릴 메모리DC생성

MemDC.CreateCompatibleDC(pDC); //화면 DC와 메모리 DC 호환 생성

CBitmap *pOldBitmap=MemDC.SelectObject(&m_bitmap); //메모리에 그림을그린다.

pDC->BitBlt(int x, int y,int Width, int Height, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop);

//BitBlt(그림x좌표,그림y좌표,그림넓이,그림높이,그림그려진메모리DC,그림시작x좌표,그림시작y좌표,스타일);

pDC->StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop )

//StretchBlt(그림x좌표,그림y좌표,그림넓이,그림높이,그림그려진메모리DC,그림x좌표,그림y좌표,메모리그림넓이,메모리그림높이,스타일);

MemDC.SelectObject(pOldBitmap); // 메모리DC반환


23. Font 바꾸기

CFontDialog dlg;//폰트다이얼로그 생성

LOGFONT m_logFont; //폰트받을변수선언

if(dlg.DoModal()==IDOK) //폰트다이얼로그표시

{dlg.GetCurrentFont(&m_logFont)} //선택된 폰트받기

OnDraw()

CFont newFont,*pOldFont; //폰트 객체 만들기

newFont.CreateFontIndirect(&m_logFont); //폰트 생성

pOldFont=(CFont *)pDC->SelectObject(&newFont); //폰트 선택

OnCreate()

CClientDC dc(this); //DC 생성

CFont *pFont=dc.GetCurrentFont(); //클라이언트 영역의 폰트를

pFont->GetLogFont(&m_logFont); //로그폰트 멤버값으로 지정


24. Font 만들기

LOGFONT logfont; //폰트를 만든다

logfont.lfHeight=50; //문자열 높이

logfont.lfWidth=0; //너비

logfont.lfEscapement=0; //문자열기울기

logfont.lfOrientation=0; //문자개별각도

logfont.lfWeight=FW_NORMAL; //굵기

logfont.lfItalic=TRUE; //이탤릭

logfont.lfUnderline=TRUE; //밑줄

logfont.lfStrikeOut=FALSE; //취소선

logfont.lfCharSet=HANGUL_CHARSET; //필수

logfont.lfOutPrecision=OUT_DEFAULT_PRECIS;

logfont.lfClipPrecision=CLIP_DEFAULT_PRECIS; //가변폭폰트 고정폭폰트

logfont.lfPitchAndFamily=DEFAULT_PITCH|FF_SWISS; //글꼴이름

strcpy(logfont.lfFaceName,"궁서체");

CClientDC dc(this);

CFont newFont; //폰트객체생성

newFont.CreateFontIndirect(&logfont); //폰트지정

CFont *pOldFont=dc.SelectObject(&newFont); //폰트선택

dc.TextOut(100,100,m_text);

dc.SelectObject(pOldFont); //폰트반환


25. Font 만들기 2

CFont newFont;

newFont.CreateFont( int nHeight, int nWidth, int nEscapement, int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline, BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision, BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily, LPCTSTR lpszFacename );

CFont *pOldFont=dc.SelectObject(&newFont);


26. ComboBox 사용하기

CComboBox combo; //콤보박스 선언

combo.Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );

//Style - WS_CHILD|WS_VISIBLE

int n=combo.GetCurSel(); //선택된 아이템의 index를 가져온다

combo.AddString("문자열“); //문자열을 추가한다

combo.GetLBText(n,str); //n번째 아이템을 str에 저장


27. Spin 사용하기

Spin은 바로앞의 Tab Order에 따라 붙는다

m_spinr.SetRange(1900,3000); //스핀 범위 지정

m_spinr.SetPos(m_nYear); //스핀 위치 지정


28. CTime사용하기

CTime time; //시간객체생성

time=CTime::GetCurrentTime(); //현재시간을 저장

time.GetYear(),time.GetMonth();,time.GetDay(),time.GetHour(),time.GetMinute(),time.GetSecond()


29. CListBox 메소드

AddString("문자열"); //리스트에 문자열 추가

DeleteString(index); //리스트에서 항목 삭제

GetCount() //전체 항목 갯수를 얻는다.

GetSelcount() //선택된 항목 갯수 리턴

GetSel() //선택된 것인지 아닌지를 리턴한다 -> 양수 = TRUE , 음수 => FALSE

GetText(int index,문자열변수) //index 번째 문자열을 문자열 변수에 넣는다

FindStringExact(문자열) //지정 문자열의 index 값 리턴 -> 없으면 리턴값 LB_ERR 반환

FindString("a") //"a"로 시작하는 항목을 모두 찾는다.

ResetCountent() //모든 내용을 지운다.


30. 파일입출력

프로젝트생성시 Step4 => Advanced => 저장파일확장자지정

//이 클래스를 저장,로드가능한 클래스로 쓰겟다는 선언

.h 파일에 DECLARE_SERIAL(CSawon)

.cpp 파일에 IMPLEMENT_SERIAL(CSawon,CObject,1) //이거를 해야 저장이 가능하다

void CFileioDoc::Serialize(CArchive& ar)

if (ar.IsStoring())

{

ar< < //저장하기

}

else //열기

{

ar>>m_shape; //불러올걸 쓴다. 읽을때도순서대로읽어야한다

}


31. MicroSoft FlexGrid 사용하기!

CMSFlexGrid m_Grid; //FlexGrid 컨트롤 변수

CString strTitle[]={"고객코드","고객성명","고객포인트","신장","몸무게","고객등급","BMT지수","판정결과"}; // Grid 의 제목에 넣을문자배열

int Width[]={900,900,1100,800,800,900,1000,900}; // Grid 의 열넓이 지정할 배열

m_Grid.SetRows(m_cnt+2); //전체행수 지정

m_Grid.SetCols(8);//전체열수 지정

m_Grid.Clear(); //지우기

m_Grid.SetFixedCols(0); //고정열은 없다.

m_Grid.SetRow(0); // 행선택

for(int i=0;i<=7;i++)

{

m_Grid.SetColWidth(i,Width[i]); //열 넓이 설정

m_Grid.SetCol(i); //열 선택

m_Grid.SetText(strTitle[i]); // 선택된행, 선택된열에 Text 를 넣는다

}


32. 4대 Class간 참조

//각각 헤더파일 include

#include "MainFrm.h" //메인프레임 헤더파일

#include "ClassDoc.h" //Doc클래스 헤더파일

#include "ClassView.h" //View를 include 할때는 반드시 Doc 헤더파일이 위에잇어야한다

#include "Class.h" //APP Class 의 헤더파일


void CClassView::OnMenuView() //뷰클래스

CClassApp *pApp=(CClassApp *)AfxGetApp(); //View -> App
CMainFrame *pMain=(CMainFrame *)AfxGetMainWnd(); //View -> MainFrm

//View -> MainFrm -> Doc

CClassDoc *pDoc=(CClassDoc *)pMain->GetActiveDocument();

CClassDoc *pDoc=(CClassDoc *)GetDocument(); //View -> Doc


//MainFrame 클래스

CClassView *pView=(CClassView *)GetActiveView(); //MainFrm -> View

CClassDoc *pDoc=(CClassDoc *)GetActiveDocument(); //MainFrm -> Doc

CClassApp *pApp=(CClassApp *)AfxGetApp(); //MainFrm -> App


//Doc 클래스

CClassApp *pApp=(CClassApp *)AfxGetApp(); //Doc -> App

CMainFrame *pMain=(CMainFrame *)AfxGetMainWnd(); //Doc -> MainFrm

// Doc -> MainFrm -> View

CClassView *pView=(CClassView *)pMain->GetActiveView();

CClassView *pView=(CClassView *)m_viewList.GetHead(); // Doc -> View


//App 클래스

CMainFrame *pMain=(CMainFrame *)AfxGetMainWnd(); //App -> MainFrm

//App -> MainFrm -> View

CClassView *pView=(CClassView *)pMain->GetActiveView();

//App -> MainFrm -> Doc

CClassDoc *pDoc=(CClassDoc *)pMain->GetActiveDocument();


33. ToolBar 추가하기

CMainFrame 으로 가서 멤버변수 추가

CToolBar m_wndToolBar1;

OnCreate 로 가서 다음 내용을 추가해준다

(위의 toolbar 부분을 복사하고 이름만 바꾸면 된다.3군데..)

if (!m_wndToolBar1.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE |

CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY |

CBRS_SIZE_DYNAMIC) || !m_wndToolBar1.LoadToolBar(IDR_TOOLBAR1))

{

TRACE0("Failed to create toolbar\n");

return -1; // fail to create

}


그 함수내에서 //TODO 아래에 내용추가..역시..복사해서 이름만 바꾸면 된다.

m_wndToolBar1.EnableDocking(CBRS_ALIGN_TOP|CBRS_ALIGN_BOTTOM);

//DockControlBar(&m_wndToolBar1); <= 이부분 대신..

이거를 넣는다..

CRect toolRect; //툴바 영역을 얻을 사각형

this->RecalcLayout(); //현상태의 Client 영역을 구해서 저장한다

m_wndToolBar.GetWindowRect(&toolRect); //툴바영역을 저장한다

toolRect.left+=1; //사각형의 왼쪽을 1Pixel 줄인다

//ToolRect에 툴바를 붙인다

DockControlBar(&m_wndToolBar1,AFX_IDW_DOCKBAR_TOP,&toolRect);

return 0;


34. ToolBar에 ComboBox붙이기

CComboBox m_combo; //객체생성

ID 등록 => view 메뉴 => resource symbol => new => ID_COMBO

oncreate 에 내용 추가 (콤보를 만들고 표시하는 내용)

m_wndToolBar.SetButtonInfo(10,IDC_COMBO,TBBS_SEPARATOR,150);

//툴바의 10번째버튼을 편집한다

CRect itemRect; //콤보를넣을 사각형을 만든다

m_wndToolBar.GetItemRect(10,&itemRect); //툴바의 10번째 버튼을 사각형에 넣는다
itemRect.left+=5; //앞여백

itemRect.right+=5; //뒤여백

itemRect.bottom+=100; //콤보가열릴 공간확보

m_combo.Create(WS_CHILD|WS_VISIBLE|CBS_DROPDOWN,itemRect,&m_wndToolBar,IDC_COMBO);

//콤보박스를 툴바에 붙여준다

m_combo.AddString("이름"); //내용추가

m_combo.SetCurSel(0); //셀 선택


35. Toolbar에 수동으로넣은 ComboBox 사용하기

afx_msg void [안내]태그제한으로등록되지않습니다-xxOnSelectCombo(); //원형

ON_CBN_SELCHANGE(IDC_COMBO,[안내]태그제한으로등록되지않습니다-xxOnSelectCombo) //메세지맵에 추가

CMainFrame *pMain=(CMainFrame *)GetParent(); //메인프레임 주소참조

CComboBox *pCom=(CComboBox *)(pMain->m_wndToolBar.GetDlgItem(IDC_COMBO));

//콤보박스의 주소를 가져온다, 접근할 때 메인프레임 -> 툴바 -> 콤보박스 의 순서로 가야한다

int n=pCom->GetCurSel(); //현재선택된 셀의 인덱스를 가져온다

if(n==CB_ERR) return; //선택된셀이 없으면 중지한다

CString str;

pMain->m_combo.GetLBText(n,str); //선택된셀의 Text를 가져온다


36. UPDATE_COMMAND 사용하기

pCmdUI->Enable(TRUE); //버튼 활성화

pCmdUI->SetText((bAdd)?"취소":"신규"); //버튼의 text 설정

pCmdUI->SetCheck(TRUE);//버튼 체크


37. 프로그램정보저장

CWinApp::GetProfileString(섹션명,항목명,기본값); // 함수를 사용한다. (문자열)

CWinApp::GetProfileInt(섹션명,항목명,기본값); //불러올때사용 (숫자)

CWinApp::WriteProfileString(섹션명,항목명,값); //저장할때 사용 (문자열)

CWinApp::WriteProfileInt(섹션명,항목명,값); //저장할때 사용 (숫자)

//불러올때 사용할함수

void CMainFrame::ActivateFrame(int nCmdShow) //프로그램 실행후 프레임생성될때 실행

//저장할 때 WM_DESTROY 메시지 사용


38. 컨트롤바 표시하기

CMainFrame *pMain=(CMainFrame *)GetParent();//MainFrame 주소가져오기

//툴바를 bTool2 에따라 보이고 감춘다

pMain->ShowControlBar(&pMain->m_wndToolBar,bTool1,FALSE);


39. Window 창크기,위치정보 저장하기

MainFrame 의 WM_DESTROY 에

WINDOWPLACEMENT w;

this->GetWindowPlacement(&w); //윈도우의 정보를 저장한다.

CString strRect;

strRect.Format("%04d,%04d,%04d,%04d", //04d 는 4자리 확보하고 남은건 0으로 채워라

w.rcNormalPosition.left,w.rcNormalPosition.top,

w.rcNormalPosition.right,w.rcNormalPosition.bottom); //윈도우의 위치,크기 확보..

BOOL bMax,bMin; //윈도우의 상태를 저장하기위한 변수

//w.falg 는 이전상태의 정보를 가지고 잇다!!

if(w.showCmd==SW_SHOWMINIMIZED) //최소화 상태

{

bMin=TRUE;

if(w.flags==0) //falg 값이 0 이면 이전 상태가 보통상태이다!!

bMax=FALSE;

else //이전상태가 최대화 상태

bMax=TRUE;

}

else

{

if(w.showCmd==SW_SHOWMAXIMIZED) //최대화상태

{

bMax=TRUE;

bMin=FALSE;

}

else //보통 상태

{

bMax=FALSE;

bMin=FALSE;

}

}

AfxGetApp()->WriteProfileString("WinStatus","Rect",strRect);

AfxGetApp()->WriteProfileInt("WinStatus","Max",bMax);

AfxGetApp()->WriteProfileInt("WinStatus","Min",bMin);


//읽어올차례..

ActivateFrame 함수로 가서

WINDOWPLACEMENT w; //윈도우의 상태를 저장하는 구조체..

BOOL bMax,bMin; //최대,최소상태를 저장할 변수

CString strRect; //창크기를 받아올 변수

strRect=AfxGetApp()->GetProfileString("WinStatus","Rect","0000,0000,0500,0700");

bMin=AfxGetApp()->GetProfileInt("WinStatus","Min",FALSE);

bMax=AfxGetApp()->GetProfileInt("WinStatus","Max",FALSE);

int a=atoi(strRect.Left(4)); //문자열을 int 로 바꿔준다.

int b=atoi(strRect.Mid(5,4)); //atoi 아스키 값을 int형으로 바꿔준다..

int c=atoi(strRect.Mid(10,4));

int d=atoi(strRect.Mid(15,4));

w.rcNormalPosition=CRect(a,b,c,d);

if(bMin)

{

w.showCmd=SW_SHOWMINIMIZED;

if(bMax)

{

w.flags=WPF_RESTORETOMAXIMIZED ;

}

else

{

w.flags=0;

}

}

else

{

if(bMax)

{

w.showCmd=SW_SHOWMAXIMIZED;

}

else

{

w.showCmd=SW_SHOWNORMAL;

}

}

this->SetWindowPlacement(&w); //설정된 값으로 윈도우를 그리게 한다..

//CFrameWnd::ActivateFrame(nCmdShow); //이건 반드시 주석처리한다..


40. progress Bar 쓰기

m_progress.SetRange(m_first,m_last); //Progress 범위설정하기

m_progress.SetStep(m_step); //Progress Step설정하기

//m_progress.StepIt(); //스텝만큼 움직이기

//또는 다음을 사용한다

for(int a=m_first;a<=m_last;a+=m_step) //a가 처음부터 끝까지

{

m_progress.SetPos(a); // 위치를 a에 맞춘다

Sleep(50); //천천히 움직이게한다

}


41. 파일대화상자 FileDialog 사용하기

void CConDlg1::OnFileopen() //파일열기 버튼

{

CFileDialog *fdlg; //파일대화상자 객체 생성 // 포인터로 만든다..

static char BASED_CODE szFilter[] = "Animate Video Files (*.avi)|*.avi|All Files

(*.*)|*.*||";

//필터를 만들어 준다..이건 할줄 모름..

fdlg =new CFileDialog(TRUE, ".avi", NULL, OFN_HIDEREADONLY |

OFN_OVERWRITEPROMPT,szFilter);

//대화상자 만들기..이렇게 해야댄다..

if(fdlg->DoModal()==IDOK) //이제..대화상자를 띠우고..

{ //OK 누르면 실행될 부분..

m_filename=fdlg->GetPathName(); //대화상자에서 경로를 받아서 저장.

UpdateData(FALSE);

}

}

//파일 다이얼로그 만들기

CFileDialog fdlg(TRUE,"avi",".avi",OFN_OEVRWRITEPROMPT,"Vidoe Files(*.avi)

|*.avi|All Files(*.*)|*.*||");

42. Animate Control 사용하기

m_animate.Open(m_filename); //파일을 연다

m_animate.Play(0,-1,1); //(처음프레임,마지막프레임,반복횟수)

m_animate.Stop(); //정지시키기

m_ani.SetAutoStart(TRUE);//자동으로 시작한다

43. Control 의 Style 바꿔주기

Control.ModyfyStyle(제거할스타일,추가할스타일); //스타일은 MSDN내용 참조


44. 시스템 날자바꾸기 버튼

SetSystemTime(),GetSystemTime() //GMT 표준시를 가져온다.

GetLocalTime(),SetLocalTime() //현재 지역시간을 가져온다.


SYSTEMTIME st;

GetLocalTime(&st); //현재 시간, 날자를 넣는다.

st.wYear=m_date2.GetYear();

st.wMonth=m_date2.GetMonth();

st.wDay=m_date2.GetDay();

SetSystemTime(&st);


45. 시스템 시간 바꾸기 버튼

UpdateData(TRUE);

SYSTEMTIME st;

GetLocalTime(&st);

st.wHour=m_time.GetHour();

st.wMinute=m_time.GetMinute();

st.wSecond=m_time.GetSecond();

SetLocalTime(&st);


46.시스템의 드라이브 문자 얻기

char temp[50];

GetLogicalDriveStrings(sizeof(temp),temp);

CString str,str1;

int n=0;

while(*(temp+n)!=NULL)

{

str=temp+n;

str1+= " "+str.Left(2);

n+=4;

}


47. 현재 작업경로 얻기

char temp[MAX_PATH]; //MAX_PATH 는 경로길이의 최대를 define 해놓은것.

GetCurrentDirectory(sizeof(temp),temp); // 현작업하는 경로(경로 길이,문자형);


48. Tree Control 사용하기

HTREEITEM hmov,hmus; //핸들을받을 변수 이게 잇어야 하위 디렉토리 생성가능

hmov=m_tree.InsertItem("영화",TVI_ROOT,TVI_LAST); //,TVI_ROOT,TVI_LAST는 default

hm1=m_tree.InsertItem("외화",hmov); //hmov 아래 “외화”트리 생성

CImageList m_image; //그림을 사용하기 위한 클래스다!! 알아두자..

m_tree.SetImageList(&m_image,TVSIL_NORMAL); //Tree View Style Image List => TVSIL

hmov=m_tree.InsertItem("영화",0,1,TVI_ROOT,TVI_LAST);//TVI_ROOT,TVI_LAST는 default

hmus=m_tree.InsertItem("가요",1,2);//("문자열",처음그림번호,선택시그림)

hm1=m_tree.InsertItem("외화",2,3,hmov); //그림 번호는 default 로 0이 들어간다..


49. List Control 사용하기

m_list.ModifyStyle(LVS_TYPEMASK, LVS_ICON); //리스트를 큰아이콘형태로 보인다

m_list.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON);//리스트를 작은아이콘형태

m_list.ModifyStyle(LVS_TYPEMASK, LVS_LIST); //리스트를 리스트형태로 보인다

m_list.ModifyStyle(LVS_TYPEMASK, LVS_REPORT); //리스트를 자세히형태로 보인다

CImageList m_treeimage; //이미지리스트

CImageList m_small, m_large;

m_large.Create(IDB_LARGE,32,0,RGB(255,255,255)); //이거는 클래스에서 추가해준거다

m_small.Create(IDB_SMALL,16,0,RGB(255,255,255));// (bmp ID값,

m_list.SetImageList(&m_large,LVSIL_NORMAL);

m_list.SetImageList(&m_small,LVSIL_SMALL);

CString name[]={"홍길동","진달래","한국남","개나리"};

CString tel[]={"400-3759","304-7714","505-9058","700-9898"};

CString born[]={"1980-1-1","1981-12-20","1980-05-15","1981-08-31"};

CString sex[]={"남자","여자","남자","여자"};

m_list.InsertColumn(0,"이름",LVCFMT_LEFT,70);

m_list.InsertColumn(1,"전화번호",LVCFMT_LEFT,80);

m_list.InsertColumn(2,"생일",LVCFMT_LEFT,90);

m_list.InsertColumn(3,"성별",LVCFMT_LEFT,50);

LVITEM it; //리스트 구조체

char temp[100];

for(int a=0;a<4;a++)

{

int n=(sex[a]=="남자")?0:1;

m_list.InsertItem(a,name[a],n); //insert item 은 행을 만들고..

it.mask=LVIF_TEXT|LVIF_IMAGE; //마스크 설정

it.iItem=a;

it.iSubItem=1;//열 설정

strcpy(temp,tel[a]); //이거 모하는거냐..

it.pszText=temp;

m_list.SetItem(&it); // setitem 열에 정보를 넣는다.


it.iSubItem=2; //열 설정

strcpy(temp,born[a]); //이거 모하는거냐..

it.pszText=temp;

m_list.SetItem(&it); // setitem 열에 정보를 넣는다.


it.iSubItem=3; //열 설정

strcpy(temp,sex[a]); //이거 모하는거냐..

it.pszText=temp;

m_list.SetItem(&it); // setitem 열에 정보를 넣는다.

50. Bitmap Button 사용하기

CBitmapButton 을 사용한다! CButton 에서 상속 받는클래스임..

m_button1.Create(NULL, WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,

CRect(310,20,370,50), this,IDC_MYBUTTON); //버튼만들기

m_button1.LoadBitmapsIDB_UP,IDB_DOWN,IDB_FOCUS,IDB_DISABLE);//버튼의 그림설정

m_button1.SizeToContent(); //버튼을 그림 크기로 맞춰 준다!!


//그냥 버튼을 비트맵버튼으로 바꾸기 -> 버튼을 만든다 속성에서 OWNERDRA 속성에 체크!!

m_button2.LoadBitmaps(IDB_UP,IDB_DOWN,IDB_FOCUS,IDB_DISABLE); //버튼 그림설정

m_button2.SizeToContent(); //버튼을 그림 크기로 맞춰 준다!!


51. 중복없는 난수발생하기

int su; //발생된 난수저장

int a,b;

BOOL bDasi; //숫자가중복될경우 다시하기위한 변수

for(a=0;a<9;a++) //난수 9개 발생

{

bDasi=TRUE;

while(bDasi)

{

bDasi=FALSE;

su=rand()%10; //난수발생

for(b=0;b

{

if(temp[b]==su) //중복이면

{

bDasi=TRUE; //중복이 잇으면 다시while 문을 실행한다

break;

}//if

}//for

}//while

temp[a]=su; //중복이 아니면 대입한다

52. 메뉴 범위로 사용하기

ON_COMMAND_RANGE(ID_LEVEL3,ID_LEVEL9,OnLevel); //범위메세지 발생

//메뉴 ID의 값이 연속된 숫자일 경우 범위로 지정해서 사용할수잇다


53. 한,영 전환함수

void CCustView::SetHangul(BOOL bCheck) //T:한글 F:영문 이건 외우자..

{

//뷰클래스의 윈도우 핸들포인터를 얻는다.

HIMC hm=ImmGetContext(this->GetSafeHwnd());

if(bCheck)

{

::ImmSetConversionStatus(hm,1,0);//1은 한글 0은 영문

}

else

{

::ImmSetConversionStatus(hm,0,0); //영문으로 바꿔준다

}

::ImmReleaseContext(this->GetSafeHwnd(),hm); //장치를 풀어준다

}

#include "imm.h" //헤더 반드시 추가하고

imm32.lib (라이브러리 파일)를 반드시 링크해주어야 한다!

**** 라이브러리 추가하기

프로젝트메뉴 -> 셋팅 -> 링크탭


54. DLL함수정의하기

임포트함수 : extern "C" __declspec(dllimport) 리터형 함수명(매개변수,...) ;

- 메인프로그램에서 DLL에 있는 함수를 호출할때 사용한다.


엑스포트함수 : extern "C" __declspec(dllexport) 리터형 함수명(매개변수,...)

{

내용;

}

출처: http://weezzle.net/1882
감사합니다.

Posted by SB패밀리
프로세스 죽이기


Kernel32.dll 에 있는 ExitProcess()라는 함수에 대한 포인터를 얻고 이를
CreateRemoteThread()를 이용하여 프로세스를 호출하고 스스로 종료되게 하는 기능입니다.


BOOL SafeTerminateProcess(HANDLE hProcess, UNIT uExitCode)
{
DWORD dwTID, dwCode, dwErr = 0;
HANDLE hProcessDup = INVALID_HANDLE_VALUE;
HANDLE hRT = NULL;
HINSTANCE hKernel = GetModule Handle("Kernel32");

BOOL bSuccess = FALSE;
BOOL bDup = DuplicateHandle(GetCurrentProcess(),
hProcess,
GetCurrentProcess(),
&hProcessDup,
PROCESS_ALL_ACCESS,
FALSE,
0};
if (GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode) && (dwCode == STILL_ACTIVE) )
{
FARPROC pfnExitProc;
pfnExitProc = GetProcAddress(hKernel, "ExitProcess");
hRT = CreateRemoteThread((bDup) ? hProcessDup : hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE) pfnExitProc,
(PVOID) uExitCode, 0, &dwTID);

if (hRT == NULL) dwErr = GetLastError();
}
else
{
dwErr = ERROR_PROCESS_ABORTED;
}

if (hRT)
{
WaitForSingleObject((bDup) ? hProcessDup : hProcess, INFINITE);
Closehandle(hRT);
bSuccess = TRUE;
}

if (bDup)
CloseHandle(hProcessDup);
if (! bSuccess)
SetLastError(dwErr);

return bSuccess;
}


 

Posted by SB패밀리

[개발/MFC] 문자열 변환 BSTR to CString, CString to BSTR, BSTR to char*

VC++ , MFC에서 문자열 변환 정말 까다롭다.
더군다나 유니코드 모드는 조금더 까다로운것 같다.
아래 예제가 도움이 될 것이라 생각된다.

// Convert BSTR to CString
BSTR bsName;
CString csName;

USES_CONVERSION;
csName = OLE2A(bsName);

// Convert CString to BSTR
BSTR bsName;
CString csName;

bsName = csName.SysAllocString();

// create an OLE string
BSTR bstr = ::SysAllocString(L"Golf is fun!");

// Convert BSTR to char*
BSTR bsName;
char* sName;

bsName = OLE2A(sName);

// convert ATL::CCommBSTR to CString
CommBSTR cbsName;
CString csName;

csName = OLE2T(cbsName);

 

 


Posted by SB패밀리

[개발/MFC] LINK : fatal error LNK1000: Internal error during IncrBuildImage

Visual Studio 2008 에서 컴파일할 때 자꾸 발생하는 현상이다.


그것도 한 번씩 새로 컴파일할 때마다 발생하고 다시 빌드가 된다.


비주얼 스튜디오 2008에서 "

LINK : fatal error LNK1000: Internal error during IncrBuildImage"

가 계속 발생한다면 서비스팩 1(Service Pack 1:SP1)을 설치하면 해결이 된다고 한다.



그래서 나도 설치하려고 한다. 혹시나 영문판을 사용중이라면 서비스 팩 또한 영문버전으로 설치하기 바란다.



Microsoft Visual Studio 2008 Service Pack 1(iso)


http://www.microsoft.com/downloads/ko-kr/details.aspx?familyid=27673C47-B3B5-4C67-BD99-84E525B5CE61&displaylang=ko

 

 

아래는 참고로 비주얼 스튜디오 2010 서비스 팩 1 이다.


http://www.microsoft.com/downloads/ko-kr/details.aspx?FamilyID=75568AA6-8107-475D-948A-EF22627E57A5
Posted by SB패밀리

[개발/VC] xdebug, xlocale 관련 error

컴파일이나 빌드를 하면 xdebug, xlocale 관련 에러가 무지하게 많이 발생하는 경우가 생긴다.


이 에러는 다음과 같이 해결할 수 있다.

단 번에 해결이 안되더라도 꼼꼼하게 소스파일을 찾아서 수정해야한다.


#ifdef _DEBUG

#define new DEBUG_NEW

#endif


항상 .cpp 파일에서 위의 3줄 위에 #include 나 #pragma comment(lib, ...)를 선언해야 한다

Posted by SB패밀리