Programming/C Win32 MFC2009. 9. 2. 18:09

CEdit 컨트롤의 색상을 변경하기 위해서는 WM_CTLCOLOR을 이용한다.
일단 전역변수로 CBrush COLORREF 변수를 선언해준다.
그리고 나서 클래스 위저드에서 다이얼로그 자체의 WM_CTLCOLOR을 생성해준다.

이 녀석은 그리기 전에 메시지를 가로채서 색상을 설정해주는 역활을 한다고 한다.

OnInitDialog() 에서
    m_redcolor=RGB(255,0,0);                      // red
    m_bluecolor=RGB(0,0,255);                     // blue
    m_textcolor=RGB(255,255,255);                 // white text
    m_redbrush.CreateSolidBrush(m_redcolor);      // red background
    m_bluebrush.CreateSolidBrush(m_bluecolor);    // blue background
이런식으로 브러시와 색상을 미리 설정해준다.

그 다음에, OnCtlColor에서 GetDlgCtrlID()에 의해 분기를 쳐주면서
원하는 컨트롤의 ID에 연결해주면 원하는 색상으로 그려진다.

    pDC->SetBkColor(m_bluecolor);
    pDC->SetTextColor(m_textcolor);
    hbr = (HBRUSH) m_bluebrush;

위의 내용을 사용하면되며,
    SetBKColor()은 배경색상(기본값은 흰색)
    SetTextColor()은 글씨색상(기본값은 검은색)
을 변경해주게 된다.

브러시를 리턴함으로, 이 브러시를 이용하여 실제로 변경한 색상으로 그려주게 된다.


아래는 OnCtlColor의 기본 템플릿이다.
클래스위저드가 생성하면 // TODO 사이의 내용이 없으므로 불편하다.
HBRUSH CBarcodeDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
	
	// TODO: Change any attributes of the DC here
	switch(nCtlColor)
	{
		case CTLCOLOR_EDIT:
		case CTLCOLOR_MSGBOX:
			switch (pWnd->GetDlgCtrlID())
			{
				default:
					break;
			}
			break;

		case CTLCOLOR_STATIC:
			switch (pWnd->GetDlgCtrlID())
			{
				default:
					break;
			}
			break;

		default:
			break;
	}
	
	// TODO: Return a different brush if the default is not desired
	return hbr;
}


[링크 : http://www.codeguru.com/Cpp/controls/editctrl/backgroundcolor/article.php/c3929/#more]
[링크 : http://mind444.tistory.com/64]
Posted by 구차니
Programming/C Win32 MFC2009. 8. 25. 17:17
EndDialog(); 혹은
PostMessage(WM_CLOSE,0,0); 을 쓰라고 한다

[링크 : http://www.codeguru.com/forum/showthread.php?t=60903]


PostMessage(WM_CLOSE,0,0)는 한번 나왔다가 사라지고
EndDialog()는 아무런 흔적없이 다이얼로그를 없앤다.
[링크 : http://msdn.microsoft.com/en-us/library/ms645472%28VS.85%29.aspx]

두가지 방법중에는 EndDialog() 추천

프로토 타입은
BOOL EndDialog(     
    HWND hDlg,
    INT_PTR nResult
);

이며 실제 사용시에는 EndDialog(0); 이렇게 해줘도 무방함
Posted by 구차니
Programming/C Win32 MFC2009. 8. 25. 16:41
전에는 몰랐는데, 이번에 발생한 문제이다...

Pre- 라는 말이 붙듯, 모든 입력을 우선적으로 가로채서 처리하게 되는 녀석이다.

예를 들어
1. 다이얼로그 메인 윈도우가 있고
2. 메인 윈도우에서 엔터시에 입력을 받도록 하고
3. MessageBox로 메시지를 띄운뒤
4. 메시지 박스를 없애기 위해 엔터를 치면
무한 루프에 빠지게 된다.

포커스로 그 컨트롤에서만 입력을 받도록 해놨지만,
메시지 박스가 발생하면서 엔터를 입력 받아도 포커스를 받아가지 않는지
PreTranslateMessage 에서 처리를 하면서
계속 엔터를 인식해서 메시지 루프에 꾸역꾸역 넣어준다...

빠져 나오려면 머.. 엔터가 아닌 스페이스로 하면 빠져는 나오지만,
이래저래 상쾌하지 못한 결과..

[링크 : http://msdn.microsoft.com/en-us/library/kkbhxcs2%28VS.80%29.aspx]
Posted by 구차니
Programming/C Win32 MFC2009. 8. 20. 17:55
원래 C스타일로 fopen()을 좋아하다가
MFC 답게 CFile 클래스로 하려는데.. 아래처럼 배를짼다.


해결방법 : 논리 OR 의 CFile::modeReadCFile::modeWrite 대신 CFile::modeReadWrite를 지정하십시오
현재상태 : 이 동작은 의도적으로입니다.

[링크 : http://support.microsoft.com/kb/181880]

의도적이란다... 뭥미?



사족 : 혹시 저기 확인 누르신분 손?
Posted by 구차니
Programming/C Win32 MFC2009. 8. 19. 12:06
ODBC - Open DataBase Connection
DAO - Data Access Object
ADO - ActiveX Data Object


OBDC는 db 연결을 위한 일종의 드라이버/API이고
DAO는 access에서 사용하는 로컬 database 파일에 접근하는데 유용하고
ADO는 개발에 편하고, 웹어플에서 주로 사용한다고 한다.

[링크 : http://blog.naver.com/hp925/80014754374]
Posted by 구차니
Programming/C Win32 MFC2009. 7. 27. 15:46
NAME
       strtol, strtoll, strtoq - convert a string to a long integer

SYNOPSIS
       #include <stdlib.h>

       long int
       strtol(const char *nptr, char **endptr, int base);

       long long int
       strtoll(const char *nptr, char **endptr, int base);

DESCRIPTION
       The  strtol()  function  converts the initial part of the string in nptr to a long integer value according to the
       given base, which must be between 2 and 36 inclusive, or be the special value 0.

       The string may begin with an arbitrary amount of white space (as determined by isspace(3)) followed by  a  single
       optional  ‘+’ or ‘-’ sign.  If base is zero or 16, the string may then include a ‘0x’ prefix, and the number will
       be read in base 16; otherwise, a zero base is taken as 10 (decimal) unless the next character is  ‘0’,  in  which
       case it is taken as 8 (octal).

       The remainder of the string is converted to a long int value in the obvious manner, stopping at the first charac-
       ter which is not a valid digit in the given base.  (In bases above 10, the letter ‘A’ in either  upper  or  lower
       case represents 10, ‘B’ represents 11, and so forth, with ‘Z’ representing 35.)

       If  endptr  is not NULL, strtol() stores the address of the first invalid character in *endptr.  If there were no
       digits at all, strtol() stores the original value of nptr in *endptr (and returns 0).  In particular, if *nptr is
       not ‘\0’ but **endptr is ‘\0’ on return, the entire string is valid.

       The strtoll() function works just like the strtol() function but returns a long long integer value.

RETURN VALUE
       The  strtol() function returns the result of the conversion, unless the value would underflow or overflow.  If an
       underflow occurs, strtol() returns LONG_MIN.  If an overflow occurs, strtol() returns LONG_MAX.  In  both  cases,
       errno is set to ERANGE.  Precisely the same holds for strtoll() (with LLONG_MIN and LLONG_MAX instead of LONG_MIN
       and LONG_MAX).

EXAMPLE
       The  program  shown  below  demonstrates the use of strtol().  The first command line argument specifies a string
       from which strtol() should parse a number.  The second (optional) argument specifies the base to be used for  the
       conversion.   (This argument is converted to numeric form using atoi(3), a function that performs no error check-
       ing and has a simpler interface than strtol().)  Some examples of the results produced by this  program  are  the
       following:

         $ ./a.out 123
         strtol() returned 123
         $ ./a.out ’    123’
         strtol() returned 123
         $ ./a.out 123abc
         strtol() returned 123
         Further characters after number: abc
         $ ./a.out 123abc 55
         strtol: Invalid argument
         $ ./a.out ’’
         No digits were found
         $ ./a.out 4000000000
         strtol: Numerical result out of range


#include "stdlib.h"
#include "limits.h"
#include "stdio.h"
#include "errno.h"

int main(int argc, char *argv[]) { int base; char *endptr, *str; long val;
if (argc < 2) { fprintf(stderr, "Usage: %s str [base]\n", argv[0]); exit(EXIT_FAILURE); }
str = argv[1]; base = (argc > 2) ? atoi(argv[2]) : 10;
errno = 0; /* To distinguish success/failure after call */ val = strtol(str, &endptr, base);
/* Check for various possible errors */
if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0)) { perror("strtol"); exit(EXIT_FAILURE); }
if (endptr == str) { fprintf(stderr, "No digits were found\n"); exit(EXIT_FAILURE); }
/* If we got here, strtol() successfully parsed a number */
printf("strtol() returned %ld\n", val);
if (*endptr != ’\0’) /* Not necessarily an error... */ printf("Further characters after number: %s\n", endptr);

exit(EXIT_SUCCESS); }



atoi 보다 막강한 함수라고 한다.

[링크 : http://en.wikipedia.org/wiki/Strtol]
[링크 : http://linux.die.net/man/3/strtol]
Posted by 구차니
Programming/C Win32 MFC2009. 7. 13. 12:28
CTreeCtrl은 탐색기의 디렉토리를 보여주는 녀석이다
트리컨트롤에 데이터를 넣는 방법은 InserItem 이라는 함수를 사용하면 되는데,
이 함수를 유심히 살펴보면 HTREEITEM hParen = TVI_ROOT 라는 것이 있다.

// afxcmn.h
// Operations
	HTREEITEM InsertItem(LPTVINSERTSTRUCT lpInsertStruct);
	HTREEITEM InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage,
		int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam,
		HTREEITEM hParent, HTREEITEM hInsertAfter);
	HTREEITEM InsertItem(LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT,
		HTREEITEM hInsertAfter = TVI_LAST);
	HTREEITEM InsertItem(LPCTSTR lpszItem, int nImage, int nSelectedImage,
		HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST);

// commctrl.h #define TVI_ROOT ((HTREEITEM)0xFFFF0000) #define TVI_FIRST ((HTREEITEM)0xFFFF0001) #define TVI_LAST ((HTREEITEM)0xFFFF0002) #define TVI_SORT ((HTREEITEM)0xFFFF0003)

별 다른 것은 없고, 이번에 추가하는 아이템은 Root 아이템으로 적용을 하라는 것인데,
Root 아이템은 위의 이미지에서 Expanded Node / Leaf 라는 두녀석이다.
아무튼 위와 같이 tree 구조로 넣기위해서는 InserItem 함수의 return 값을 유심히 봐야한다.

HTREEITEM InsertItem(LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST);

InsertItem은 리턴값으로 추가한 녀석의 핸들을 돌려준다.
그리고 입력으로 TVI_ROOT가 들어가거나 혹은 핸들이 들어간다.



위와 같은 구조로 하기 위해서는 아래와 같이 구현하면 된다.

HTREEITEM expand;
HTREEITEM expand_2nd;
HTREEITEM expand_3rd;

expand= InsertItem("Expanded Node", TVI_ROOT, TVI_LAST);
expand_2nd = InsertItem("Expanded Node", expand, TVI_LAST);
                            InsertItem("Leaf", expand_2nd, TVI_LAST);
                            InsertItem("Leaf", expand_2nd, TVI_LAST);
expand_3rd = InsertItem("Collapsed Node", expand, TVI_LAST);
                            InsertItem("Leaf", expand_3rd, TVI_LAST);
                            InsertItem("Leaf", expand_3rd, TVI_LAST);
InsertItem("Leaf", TVI_ROOT, TVI_LAST);


[링크 : http://msdn.microsoft.com/ko-kr/library/7w95665f%28VS.80%29.aspx] CTreeCtrl Members
[링크 : http://msdn.microsoft.com/ko-kr/library/cc468290%28VS.71%29.aspx]
Posted by 구차니
Programming/C Win32 MFC2009. 6. 23. 18:33
CTime은 실질적으로 처음 사용하는 녀석인데.. 이름대로, Time/Date 관련 클래스이다.
사용방법은 매우 직관적으로
CTime::GetCurrentTime(); 를 사용하여 현재시간을 받아 온 후
GetYear() GetMonth() GetDay() GetHour() GetMinute() GetSecond()
메소드 들을 이용하여 시간 정보를 받아와서 사용하면 된다.



CFile 역시 실질적으로 처음 사용하는 녀석인데, 평소 습관대로 fopen()을 사용하려다
큰 마음먹고, MFC 답게 CFile 클래스로 처리해 보았다.


아무튼 플래그들은 다음과 같다.
	enum OpenFlags {
		modeRead =          0x0000,
		modeWrite =         0x0001,
		modeReadWrite =     0x0002,
		shareCompat =       0x0000,
		shareExclusive =    0x0010,
		shareDenyWrite =    0x0020,
		shareDenyRead =     0x0030,
		shareDenyNone =     0x0040,
		modeNoInherit =     0x0080,
		modeCreate =        0x1000,
		modeNoTruncate =    0x2000,
		typeText =          0x4000, // typeText and typeBinary are used in
		typeBinary =   (int)0x8000 // derived classes only
};

주로 쓰이는건, CFile::modeCreate와 CFile::modeWrite인데, fopen()과 비교하자면 "w" 에 속한다.
fopen()에서 사용하던 추가모드(Append)가 없어서 고심을 하다가, 아래의 사이트에서 발견하게 되었다.

outFile.Open("myFile.txt", CFile::modeNoTruncate | CFile::modeCreate | CFile::modeWrite); 
outFile.SeekToEnd(); 

[링크 : http://www.eggheadcafe.com/forumarchives/vcmfc/jun2005/post23419185.asp]

아무튼
CFile::modeWrite만 사용하면, Create가 되지 않아 파일이 없을 경우 에러가 발생한다.

CFile::modeCreate | CFile::modeWrite 를 사용하면, 덮어 써지는데 써진 내용이 이전에 쓰여진 내용보다 적으면
이전 내용이 남아 있는다. 비유를 하자면, 수정(Overlay)모드에서 가장 첫 줄 첫 칸부터 내용을 치는 것과 비슷하게 작동한다.
테스트 해봐야 하겠지만, 굳이 CFile::modeNoTruncate 를 사용하지 않더라도,
SeekToEnd()만 적용해도(Create/Write 사용) 충분하지 않을까 생각이 된다.


Posted by 구차니
Programming/C Win32 MFC2009. 6. 22. 15:57

int nCount = m_var1.GetCount();
if (nCount > 0)
 m_var1.SetCurSel(nCount - 1);

간단하게 구현되는데, 깔끔하지는 않다.
(무조건 마지막꺼를 선택하게 해서 강제로 스크롤 되기 때문에, 중앙에 놔두었을때 멈춰있지 못하다)

[링크 : http://social.msdn.microsoft.com/forums/en-US/vssmartdevicesnative/thread/9e54372f-c784-4c8f-ab4c-adc6bbe8810a]

'Programming > C Win32 MFC' 카테고리의 다른 글

CTreeCtrl - 트리구조로 데이터 넣어주기  (0) 2009.07.13
CFile / CTime  (0) 2009.06.23
MFC PreTranslateMessage() 리턴값의 의미  (0) 2009.06.17
signed type의 %X 출력  (0) 2009.06.17
CEdit Multiline사용시 개행 방법  (0) 2009.06.17
Posted by 구차니
Programming/C Win32 MFC2009. 6. 17. 16:26
PreTranslateMessage() 는, 키를 먼저(Pre) 해석해서 처리하는 메소드이다.
아래의 내용처럼, 내부에서 처리할 것 들 다 처리하고

return TRUE;
를 할 경우에는 0이 아닌 값이므로, 더 이상 처리하지 않고,

return FALSE;
일 경우에는 0이므로 계속 처리를 하도록 한다.

Return Value
Nonzero if the message was translated and should not be dispatched;
0 if the message was not translated and should be dispatched.

[링크 : http://msdn.microsoft.com/en-us/library/kkbhxcs2(VS.80).aspx]

[발견 : http://a.tk.co.kr/252]
Posted by 구차니