전에는 몰랐는데, 이번에 발생한 문제이다...

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

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

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

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

[링크 : http://msdn.microsoft.com/en-us/library/kkbhxcs2%28VS.80%29.aspx]
Posted by 구차니

댓글을 달아 주세요

원래 C스타일로 fopen()을 좋아하다가
MFC 답게 CFile 클래스로 하려는데.. 아래처럼 배를짼다.


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

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

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



사족 : 혹시 저기 확인 누르신분 손?
Posted by 구차니

댓글을 달아 주세요

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 구차니
TAG ADO, DAO, ODBC

댓글을 달아 주세요

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 구차니
TAG strrol

댓글을 달아 주세요

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 구차니

댓글을 달아 주세요

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 구차니

댓글을 달아 주세요


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]
Posted by 구차니

댓글을 달아 주세요

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 구차니

댓글을 달아 주세요

char 형의 변수를
Format("%02X");
로 출력을 했더니 0xFFFFFFFF 이런식으로 출력이된다. OTL
내가 원한건 0xFF 이런식!


해결책 : char 형 변수를 BYTE로 선언해준다.
            BYTE는 unsigned char 형으로 선언되어 있고, 이로 인해 의도한대로 출력이 될 것이다.

[링크 : http://kuaaan.tistory.com/58]
Posted by 구차니

댓글을 달아 주세요

CEdit에서는 DOS 답게, CR/LF로 개행을 한다.
그런 이유인지 모르겠지만?


아무튼 multiline을 설정했을때, 개행을 하기 위해서는
"\n"이 아니라 "\r\n"을 해주어야 한다.

위는 \n
아래는 \r
Posted by 구차니

댓글을 달아 주세요