2010/01/26 20:20
원본 : http://greenmaru.com/4

참고: http://msdn.microsoft.com/en-us/library/bb773559(VS.85).aspx

폴더 및 파일 경로 조작에 필요한 API 정리.

이런 API들이 있는걸 모르고 몇개는 필요할때 만들어서 쓰기도 했었는데-_-..
아무래도,간단하게 직접 구현한 함수들 보다는 더 꼼꼼하게 만들어져 있다. (적어도 내가 만든 것들 보다는;;)

A부터 Z까지 직접 만들어서 써야 만족하는 변태-_-가 아니라면 참고해보자.
굵게(Bold)처리한 함수들은 자주 쓰일법한 녀석들이다.

사용하기 위해서는 shlwapi.h를 include하고 shlwapi.lib를 링크해야 한다.

LPTSTR PathAddBackslash( LPTSTR lpszPath );

Adds a backslash to the end of a string to create the correct syntax for a path. If the source path already has a trailing backslash, no backslash will be added.

경로 문자열의 맨 뒤에 '\'를 붙여준다. 만약 이미 '\'문자로 종결된 상태라면 아무일도 하지 않는다.
lpszPath는 MAX_PATH크기(또는 그 이상)이라야 하며, lpszPath에 '\'를 더 붙일 수 없다면 NULL이 반환된다.

BOOL PathAddExtension( LPTSTR pszPath, LPCTSTR pszExtension );

Adds a file extension to a path string.

파일 경로(pszPath)의 맨 뒤에 지정된 확장자를 붙여준다.
만약 pszPath가 이미 확장자가 포함된 파일 경로라면 아무일도 하지 않는다.
pszExtension이 NULL이라면 기본적으로 ".exe"가 붙는다.

BOOL PathAppend( LPTSTR pszPath, LPCTSTR pszMore );

Appends one path to the end of another.

두개의 경로 문자열 결합. pszPath에 pszMore를 붙여준다. 필요하다면 '\' 문자를 사용해 결합한다.

LPTSTR PathBuildRoot( LPTSTR szRoot, int iDrive );

Creates a root path from a given drive number.

드라이브 식별 번호(iDrive)를 문자열 형(szRoot)으로 변환해 준다. 0 = a:\ 뭐 이런식이다.

BOOL PathCanonicalize( LPTSTR lpszDst, LPCTSTR lpszSrc );

Canonicalizes a path.

경로에 상대경로 지정문자 ( "./", "../")가 포함되어 있다면 이를 적절하게 처리해준다. lpszsrc="c:\\a\\b\\..\\c" temp_src="c:\\a\\b\\..\\c"라면 lpszDst = "c:\\a\\c"가 된다.

LPTSTR PathCombine( LPTSTR lpszDest, LPCTSTR lpszDir, LPCTSTR lpszFile );

Concatenates two strings that represent properly formed paths into one path; also concatenates any relative path elements.

폴더 경로 + 파일경로로 구성해준다. lpszDest = lpszDir + lpszFile.
적절하게 '\'를 사용해서 연결해 주며, 상대경로가 포함되어 있다면 이또한 적절하게 처리해 준다.
적절한 함수로군-ㅅ-ㅋㅋ

int PathCommonPrefix( LPCTSTR pszFile1, LPCTSTR pszFile2, LPTSTR pszPath );

Compares two paths to determine if they share a common prefix. A prefix is one of these types: "C:\\", ".", "..", "..\\".

두 경로 pszFile1과 pszFile2에서 어디까지가 공통된 경로인지 조사하고, pszPath에 공통된 부분을 담아준다.
공통된 부분이 없다면 pszPath는 NULL로 설정된다.

BOOL PathCompactPath( HDC hDC, LPTSTR lpszPath, UINT dx );

Truncates a file path to fit within a given pixel width by replacing path components with ellipses.

lpszPath에 포함된 경로 문자열을 dx pixel 크기에 출력하기 적절하게 잘라준다.
C:\path1\path2\sample.txt
C:\path1\...\sample.txt
C:\p...\sample.txt

BOOL PathCompactPathEx( LPTSTR pszOut, LPCTSTR pszSrc, UINT cchMax, DWORD dwFlags );

Truncates a path to fit within a certain number of characters by replacing path components with ellipses.

PathCompactPath와 유사하다. 다만, pixel단위가 아니라 최대 cchMax만큼 잘라낸다.

HRESULT PathCreateFromUrl( LPCTSTR pszUrl, LPTSTR pszPath, LPDWORD pcchPath, DWORD dwReserved );

Converts a file URL to a Microsoft MS-DOS path.

URL형태로 구성된 경로를 Windows 경로 형식으로 변환해 준다. file:///c:/test.txt = c:\test.txt.
주의: S_OK가 반환되지 않았다면 pszPath는 아무런 변화도 일어나지 않았다는 소리다!!
또, 실제 URL(Web)이 아니라 Local File Url이라야 한다.

BOOL PathFileExists( LPCTSTR pszPath );

Determines whether a path to a file system object such as a file or directory is valid.

제시된 경로의 파일/폴더가 실제로 존재하는지 검사한다.

LPTSTR PathFindExtension( LPCTSTR pPath );

Searches a path for an extension.

파일 경로에서 확장자를 찾아준다. (pPath에서 확장자가 시작되는 위치를 반환).

LPTSTR PathFindFileName( LPCTSTR pPath );

Searches a path for a file name.

파일 경로에서 파일 이름을 찾아준다. (pPath에서 이름이 시작되는 위치를 반환).

LPTSTR PathFindNextComponent( LPCTSTR pszPath );

Parses a path for the next path component.

다음 위치의 경로를 찾아준다. 어떤 경로에 대해 순자접근이 필요하다면 사용해볼 법 하다.
PathFindNextComponent( "c:\windows\system32" ) = windows\system32
PathFindNextComponent( "windows\system32") = system32

BOOL PathFindOnPath( LPTSTR pszFile, LPCTSTR *ppszOtherDirs );

Searches for a file.

파일을 검색한다. 만약 검색에 성공하면 pszFile에는 해당 파일의 전체 경로가 담겨져서 반환된다.
ppszOtherDirs가 NULL이라면 windows 기본 경로(system32, 환경 변수 path의 값 등)에서 파일을 검색한다.
주의: 여러개의 파일이 존재 하더라도, 첫번째로 검색된 파일의 경로만 반환한다.

LPCTSTR PathFindSuffixArray( LPCTSTR pszPath, const LPCTSTR *apszSuffix, int iArraySize );

Determines whether a given file name has one of a list of suffixes.

PathFindOnPath와 유사하다. 다만, apszSuffix를 통해 검색할 경로를 여러개 지정할 수 있다. (기본경로 검색은 하지 않는다.)
주의: 대소문자를 구분한다.

LPTSTR PathGetArgs( LPCTSTR pszPath );

Finds the command line arguments within a given path.

경로에 포함된 매개변수(argv)를 찾아준다.
PathGetArgs("c:\test.exe temp.txt /x") = "temp.txt /x"

UINT PathGetCharType( TUCHAR ch );

Determines the type of character in relation to a path.

문자가 경로 문자열에 사용되면 어떤 의미인지 알려준다. 경로에 포함될 수 있는 문자인가? 경로 구분자('\')인가? 등등..
이 함수를 이용해서 경로에 사용할 수 있는 문자열인지를 검사할 수 있다.

int PathGetDriveNumber( LPCTSTR lpsz );

Searches a path for a drive letter within the range of 'A' to 'Z' and returns the corresponding drive number.

제시된 경로에 포함된 드라이브 문자(c:\) 의 식별 번호를 반환한다.

BOOL PathIsContentType( LPCTSTR pszPath, LPCTSTR pszContentType );

Determines if a file's registered content type matches the specified content type. This function obtains the content type for the specified file type and compares that string with the pszContentType. The comparison is not case-sensitive.

제시된 파일경로가(확장자만 넘겨줘도 된다;) 등록된 contents type과 일치하는지 검사한다.
PathIsContentType( "c:\temp.txt", "text/plain" ) = TRUE

BOOL PathIsDirectory( LPCTSTR pszPath );

Verifies that a path is a valid directory.

실제로 존재하는 폴더인지 확인한다.

BOOL PathIsDirectoryEmpty( LPCTSTR pszPath );

Determines whether a specified path is an empty directory.

비어있는(안에 파일이나 서브 폴더가 없는) 폴더인지 확인한다.

BOOL PathIsFileSpec( LPCTSTR lpszPath );

Searches a path for any path-delimiting characters (for example, ':' or '\' ). If there are no path-delimiting characters present, the path is considered to be a File Spec path.

제시된 경로가 파일명만으로 구성되어 있는지 조사한다.
정확히 말하자면, 경로를 구성하는데 사용되는 문자 (경로 구분자'\' 라던지, 드라이브 구분자':' 라던지..)가 포함되어 있으면 FALSE가 반환된다.
주의: 파일명으로 사용할 수 없는 문자(/, :, * 등)가 들어있는가? 를 검사하는 함수가 아니다!!

BOOL PathIsHTMLFile( LPCTSTR pszFile );

Determines if a file is an HTML file. The determination is made based on the content type that is registered for the file's extension.

제시된 경로의 확장자가 HTML 유형인가를 검사한다.
한마디로, 레지스트리에 등록된 content type이 text/html이라면 TRUE. (.htm, .html, .xhtml ...)

BOOL PathIsLFNFileSpec( LPCTSTR pszName );

Determines whether a file name is in long format.

제시된 경로가 Long File Name spec에 적합한지 검사한다. (아마 쓸 일은 거의 없을듯 싶다 -_-;)

BOOL PathIsNetworkPath( LPCTSTR pszPath );

Determines whether a path string represents a network resource.

경로가 네트워크 경로라면 TRUE. 단, 실제로 존재하는 네트워크 경로인가는 다른 얘기다!

BOOL PathIsPrefix( IN LPCTSTR pszPrefix, IN LPCTSTR pszPath );

Searches a path to determine if it contains a valid prefix of the type passed by pszPrefix. A prefix is one of these types: "C:\\", ".", "..", "..\\".

경로가 pszPrefix로 시작되는가를 검사한다. 같은 드라이브에 있는 파일인지 검사할때 유용하다.

BOOL PathIsRelative( LPCTSTR lpszPath );

Searches a path and determines if it is relative.

경로가 상대경로인지 검사한다.
주의: 파일명만 제시된 경우, 상대경로로 인식한다.
PathIsRelative("../../temp.txt") = TRUE
PathIsRelative("c:/temp.txt") = FALSE
PathIsRelative("temp.txt") = TRUE

BOOL PathIsRoot( LPCTSTR pPath );

Parses a path to determine if it is a directory root.

경로가 루트 폴더(드라이브 바로 밑)인지 검사한다.
PathIsRoot("c:\") = TRUE
PathIsRoot("c:\windows") = FALSE

BOOL PathIsSameRoot( LPCTSTR pszPath1, LPCTSTR pszPath2 );

Compares two paths to determine if they have a common root component.

pszPath1과 pszPath2가 같은 드라이브(루트폴더)에 있는지 검사한다.
PathIsSameRoot( "c:\test1\temp1.txt", "c:\test2\temp2.txt" ) = TRUE

BOOL PathIsSystemFolder( LPCTSTR pszPath, DWORD dwAttrb );

Determines if an existing folder contains the attributes that make it a system folder. Alternately, this function indicates if certain attributes qualify a folder to be a system folder.

제시된 경로가 시스템 폴더인지 검사한다.

BOOL PathIsUNC( LPCTSTR pszPath );

Determines if the string is a valid Universal Naming Convention (UNC) for a server and share path.

UNC(공유)경로인지 확인한다.
PathIsUNC("\\server\folder\") = TRUE
PathIsUNC("server\folder") = FALSE

PathIsUNCServer( LPCTSTR pszPath );

Determines if a string is a valid Universal Naming Convention (UNC) for a server path only.

PathIsUNC와 다른점은 pszPath가 서버이름만으로 구성되어야 한다는 점이다. 주의할 점은, pszPath가 "\\"만으로 된 경우도 TRUE라는 점이다.
PathIsUNCServer("\\server") = TRUE
PathIsUNCServer("\\server\folder") = FALSE

BOOL PathIsUNCServerShare( LPCTSTR pszPath );

Determines if a string is a valid Universal Naming Convention (UNC) share path, \\ server\ share.

PathIsUNC와 다른점은 pszPath가 서버이름 + 공유경로만으로 구성되어야 한다는 점이다. (PathIsUNC는 파일명까지 넘어가도 TRUE)
주의: 대부분의 PathXXX 함수가 그렇듯, pszPath가 실존하는가는 관계없다!!!

BOOL PathIsURL( LPCTSTR pszPath );

Tests a given string to determine if it conforms to a valid URL format.

유효한 URL인지 확인한다.

BOOL PathMakePretty( LPTSTR lpPath );

Converts a path to all lowercase characters to give the path a consistent appearance.

경로를 소문자로 변환해준다. 이미 소문자로 이뤄져서 변환이 이뤄지지 않은 경우 FALSE가 반환된다.
주의할 점은, lpPath가 모두 대문자로 이뤄져 있어야 변환된다는 점이다 -_-;
PathMakePretty( "C:\TEST\TEMP.TXT" ) = "c:\test\temp.txt"
PathMakePretty( "c:\Test\Temp.txt") = 변화 없음

BOOL PathMakeSystemFolder( LPTSTR pszPath );

Gives an existing folder the proper attributes to become a system folder.

지정된 폴더를 시스템 폴더로 만든다.

BOOL PathMatchSpec( LPCSTR pszFile, LPCSTR pszSpec );

Searches a string using a Microsoft MS-DOS wild card match type.

지정된 문자(열)이 경로에 포함되어 있는지 검사한다. DOS명령어 "dir *.bmp" 개념으로 생각하면 된다.
PathMatchSpec( "c:\test\temp.txt", "*.txt") = TRUE

BOOL PathMatchSpecEx( LPCTSTR pszFile, LPCTSTR pszSpec, DWORD dwFlags );

Searches a string using a Microsoft MS-DOS wild card match type and a flag.

PathMatchSpec과 유사하다. 차이점은, dwFlags에 PMSF_MULTIPLE를 사용하면 여러개의 검색 패턴 지정이 가능하다는 점.
주의: shlwapi.dll version 7.0.(Vista) 이상에서 사용 가능하다.
PathMatchSpecEx( "c:\test\temp.txt temp2.bmp", "*.txt temp.*", PMSF_MULTIPLE ) = TRUE

int PathParseIconLocation( LPTSTR pszIconFile );

Parses a file location string containing a file location and icon index, and returns separate values.

pszIconFile에 파일경로와 아이콘 인덱스가 포함되어 있는 경우 이를 적절하게 분리해 준다.
pszIconFile에는 경로가, 아이콘 인덱스는 반환값으로 나오게 되며, pszIconFile은 "경로, icon index"형식 이라야 한다.

BOOL PathQuoteSpaces( LPTSTR lpsz );

Searches a path for spaces. If spaces are found, the entire path is enclosed in quotation marks.

lpsz에서 공백이 발견되면 lpsz를 큰 따옴표(")로 묶어준다. 공백이 없다면 아무일도 하지않고 FALSE가 반환된다.

BOOL PathRelativePathTo( LPTSTR pszPath, LPCTSTR pszFrom, DWORD dwAttrFrom, LPCTSTR pszTo, DWORD dwAttrTo );

Creates a relative path from one file or folder to another.

pszFrom에서 pszTo로 가는 상대경로를 구해서 pszPath에 담아준다. 당연한 소리지만 pszFrom과 pszTo는 동일한 Prefix에서 시작해야 한다.
TCHAR buffer[MAX_PATH];
BOOL PathRelativePathTo( buffer, "c:/a/b/c/", FILE_ATTRIBUTE_DIRECTORY, "c:/a/1/2/test.txt", FILE_ATTRIBUTE_NORMAL);
buffer = "../../1/2/test.txt";

void PathRemoveArgs( LPTSTR pszPath );

Removes any arguments from a given path.

경로에 포함된 인자(argv)를 지워준다.

LPTSTR PathRemoveBackslash( LPTSTR lpszPath );

Removes the trailing backslash from a given path.

경로 맨 끝에 back slash(\)가 있다면 지워준다.

void PathRemoveBlanks( LPTSTR lpszString );

Removes all leading and trailing spaces from a string.

Trim과 유사하다. 경로 앞뒤의 공백을 제거한다.

void PathRemoveExtension( LPTSTR pszPath );

Removes the file extension from a path, if one is present.

확장자를 제거한다.

BOOL PathRemoveFileSpec( LPTSTR pszPath );

Removes the trailing file name and backslash from a path, if they are present.

파일이름을 제거한다. 주의할 점은 맨 끝의 "\"도 지워진다는거~
PathRemoveFileSpec("c:\temp\test.txt") = "c:\temp"

BOOL PathRenameExtension( LPTSTR pszPath, LPCTSTR pszExt );

Replaces the extension of a file name with a new extension. If the file name does not contain an extension, the extension will be attached to the end of the string.

파일 경로의 확장자를 지정된 확장자로 교체한다.
PathRenameExtension( "c:\temp\test.xml", ".txt") = "c:\temp\test.txt"

BOOL PathSearchAndQualify( LPCTSTR pcszPath, LPTSTR pszFullyQualifiedPath, UINT cchFullyQualifiedPath );

Determines if a given path is correctly formatted and fully qualified.

제시된 경로 pcszPath에 오류가 있다면 이를 바로잡아서 pszFullyQualifiedPath에 담아준다.
상대경로를 적절히 계산해 주고, 시스템 변수가 사용된 경우 이를 적절히 확장해 준다.
TCHAR buffer[MAX_PATH];
PathSearchAndQualify( "c:\a\..\b", buffer, MAX_PATH) = c:\b;
PathSearchAndQualify( "c:\a\\\b", buffer, MAX_PATH) = c:\a\b;
PathSearchAndQualify( "notepad.exe", buffer, MAX_PATH) = c:\windows\system32\notepad.exe;
PathSearchAndQualify( "%SystemRoot%system32\notepad.exe", buffer, MAX_PATH) = c:\windows\system32\notepad.exe;

void PathSetDlgItemPath( HWND hDlg, int id, LPCSTR pszPath );

Sets the text of a child control in a window or dialog box, using PathCompactPath to ensure the path fits in the control.

PathCompactPath와 유사하다. id로 지정된 Dialog Item에 출력하기 적합한 길이로 경로를 잘라준다.

LPCTSTR PathSkipRoot( LPCTSTR pszPath );

Parses a path, ignoring the drive letter or Universal Naming Convention (UNC) server/share path elements.

루트 경로를 제거한다. 로컬 경로인 경우 드라이브문자(c:\)가 지워지고, UNC경로인 경우 서버이름, 공유폴더 이름이 제거된다.
PathSkipRoot( "c:\temp\test.txt") = temp\test.txt
PathSkipRoot( "\\server\c$\temp\test.txt") = temp\test.txt

void PathStripPath( LPTSTR pszPath );

Removes the path portion of a fully qualified path and file.

전체 경로에서 파일이름(또는 마지막 폴더 이름)만을 남기고 제거한다.
PathStripPath("c:\temp\test.txt") = test.txt
PathStripPath("c:\temp\foo") = foo

BOOL PathStripToRoot( LPTSTR szRoot );

Removes all parts of the path except for the root information.

루트경로만 남기고 나머지를 제거한다.
PathStripToRoot("c:\temp") = c:\

void PathUndecorate( LPTSTR pszPath );

Removes the decoration from a path string.

이건 뭐라고 설명해야 되나 -_-; 예제를 보자. 참고로, "[n]"형태만 제거한다. (n), {n} 뭐 이런건 영향받지 않는다;
PathUndecorate( "temp[1].txt") = temp.txt

BOOL PathUnExpandEnvStrings( LPCTSTR pszPath, LPTSTR pszBuf, UINT cchBuf );

Replaces folder names in a fully-qualified path with their associated environment string.

경로와 일치하는 환경변수로 치환해 준다.
char szBuffer[MAX_PATH];
PathUnExpandEnvStrings( "c:\windows\", szBuffer, MAX_PATH ) = "%SystemRoot%";

BOOL PathUnmakeSystemFolder( LPTSTR pszPath );

Removes the attributes from a folder that make it a system folder. This folder must actually exist in the file system.

폴더속성에서 system속성을 제거한다.

void PathUnquoteSpaces( LPTSTR lpsz );

Removes quotes from the beginning and end of a path.

경로를 둘러싼 큰 따옴표(")를 제거해 준다.
PathUnquoteSpaces("\"c:\temp\"") = c:\temp

BOOL SHSkipJunction( IBindCtx *pbc, const CLSID *pclsid );

Checks a bind context to see if it is safe to bind to a particular component object.

...이놈은 당최 뭐에 쓰라는건지 모르겠다 -_-;

HRESULT UrlApplyScheme( LPCTSTR pszIn, LPTSTR pszOut, LPDWORD pcchOut, DWORD dwFlags );

Determines a scheme for a specified URL string, and returns a string with an appropriate prefix.

경로앞에 적절한 scheme를 붙여준다. (http://, file:///, ftp:// 등)
효과는 그닥 기대하지 말자;;

HRESULT UrlCanonicalize( LPCTSTR pszUrl, LPTSTR pszCanonicalized, LPDWORD pcchCanonicalized, DWORD dwFlags );

Converts a URL string into canonical form.

URL경로에 포함된 상대경로( '.', '..') 를 적절하게 처리한다. dwFlag값에 따라 안전하지 않은 문자들을 escape처리 하는등의 기능도 수행할 수 있다.

HRESULT UrlCombine( LPCTSTR pszBase, LPCTSTR pszRelative, LPTSTR pszCombined, LPDWORD pcchCombined, DWORD dwFlags );

When provided with a relative URL and its base, returns a URL in canonical form.

두 URL경로를 합쳐준다.
UrlCombine( "http://www.greenmaru.com/", "default.aspx", lpszCombine, &dwSize, 0 ) = "http://www.greenmaru.com/default.aspx"
주의!
UrlCombine( "http://abc.com/a/b/c", "d" ...)는 "http://abc.com/a/b/d"가 된다.
UrlCombine( "http://abc.com/a/b/c/", "d" ...)로 해야 "http://abc.com/a/b/c/d"가 된다.

int UrlCompare( LPCTSTR pszURL1, LPCTSTR pszURL2, BOOL fIgnoreSlash );

Makes a case-sensitive comparison of two URL strings.

두 URL 문자열을 비교한다. (대소문자 구분 없음)

HRESULT UrlCreateFromPath( LPCTSTR pszPath, LPTSTR pszUrl, LPDWORD pcchUrl, DWORD dwReserved );

Converts a Microsoft MS-DOS path to a canonicalized URL.

로컬 경로문자열(c:\temp)을 URL포맷(file:///c:\temp)으로 변환해준다.

HRESULT UrlEscape( LPCTSTR pszURL, LPTSTR pszEscaped, LPDWORD pcchEscaped, DWORD dwFlags );

Converts characters in a URL that might be altered during transport across the Internet ("unsafe" characters) into their corresponding escape sequences.

URL로 사용할 수 없는 문자들(^, {, " 등)을 URL encoding된 문자열로 변환해 준다.

HRESULT UrlEscapeSpaces( LPCTSTR pszURL, LPTSTR pszEscaped, LPDWORD pcchEscaped );

A macro that converts space characters into their corresponding escape sequence.

URL에 포함된 공백을 escapce처리 해 준다.

HRESULT UrlGetPart( LPCTSTR pszIn, LPTSTR pszOut, LPDWORD pcchOut, DWORD dwPart, DWORD dwFlags );

Accepts a URL string and returns a specified part of that URL.

dwPart값에 따라 URL에서 특정부분을 분리해 준다. (hostname, port...)

BOOL UrlIs( LPCTSTR pszUrl, URLIS UrlIs );

Tests whether or not a URL is a specified type.

URL이 UrlIs에 제시된 조건(적합한 URL인가? 파일 경로인가? 등)에 맞는 구성인지 확인한다.

저작자 표시 비영리 변경 금지
Posted by 태발이
2009/09/01 23:41

소스코드는 "API정복"의 저자 김상형님의 소스코드입니다.

#include 

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass=TEXT("Class");

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
	  ,LPSTR lpszCmdParam,int nCmdShow)
{
	HWND hWnd;
	MSG Message;
	WNDCLASS WndClass;
	g_hInst=hInstance;

	WndClass.cbClsExtra=0;
	WndClass.cbWndExtra=0;
	WndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
	WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
	WndClass.hInstance=hInstance;
	WndClass.lpfnWndProc=WndProc;
	WndClass.lpszClassName=lpszClass;
	WndClass.lpszMenuName=NULL;
	WndClass.style=CS_HREDRAW | CS_VREDRAW;
	RegisterClass(&WndClass);

	hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
		NULL,(HMENU)NULL,hInstance,NULL);
	ShowWindow(hWnd,nCmdShow);

	while (GetMessage(&Message,NULL,0,0)) {
		TranslateMessage(&Message);
		DispatchMessage(&Message);
	}
	return (int)Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;

	switch (iMessage) {
	case WM_CREATE:
		hWndMain=hWnd;
		return 0;
	case WM_PAINT:
		hdc=BeginPaint(hWnd, &ps);
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
저작자 표시 비영리 변경 금지
Posted by 태발이
2009/06/02 16:41

보통 디버깅용도로 쓰면 유용하게 쓸 수 있다.

헤더파일 밑에 아래 코드를 집어넣어주면 끝!!

#pragma comment(linker, "/entry:WinMainCRTStartup /subsystem:console") 
저작자 표시 비영리 변경 금지
Posted by 태발이
2009/05/28 02:25

WinDef.h 파일에 보면 MAX_PATH가 260으로 설정되어있는것을 확인할 수 있습니다.

이 길이를 폴더경로만의 길이(파일명은 제외한)로 알고계신분이 간혹 있는것 같습니다.

윈도우 탐색기에서 간단한 테스트를 해보시면 아시겠지만 전체 경로의 길이가 260인것을 확인할 수 있습니다.

이 260이란 길이 안에는 드라이브명("C:"), 폴더구분문자("\"), 파일확장자 구분문자("."), 널문자 모두 포함입니다.

예전엔 이게 윈도우즈의 버그로 작용해서, 탐색기가 죽는 현상이 발생했었는데, 현재 비스타에서 테스트해본결과

에러메시지가 잘 뜹니다.

테스트 방법은 새폴더를 하나 만드시고 폴더이름을 0123456789 를 26번 복사해서 넣어보세요.

아마 232문자만 폴더이름이 만들어질겁니다.

그리고 하위폴더로 새폴더를 만들려고하면 에러메시지가 뜹니다. 길이가 너무 길다는 메시지박스입니다.

하지만 파일은 만들어집니다. 텍스트파일을 만들어보세요.

아마 "1234567.TXT" 까지밖에 입력이 안될겁니다.

이것을 모두 조합해서 메모장에

C:\ + 폴더명 + \ + 1234567.TXT를 입력해보세요.

총 259자의 길이입니다.

그리고 마지막 문자 한개가 비어있습니다. 이부분은 바로 널문자가 들어갈 부분입니다.

그러므로 윈도우에선 드라이브명, 폴더, 파일명, 널문자 모두 합쳐서 260자까지 만들 수 있습니다.
저작자 표시 비영리 변경 금지
Posted by 태발이
2009/02/08 03:58


잠깐 군복무시절 이야기를 할께요...^^
때는 2004년부터 2006년 사이입니다. 저는 공군의 한 비행교육대대의 CQ(항공운항병)로 근무하고 있었습니다.
대대의 주 임무가 비행이다보니 대외비부터 2급비밀까지 비밀 투성이였습니다.
컴퓨터에도 위험한 문서들이 많이 있었죠. 병사들도 비밀을 만질 수 밖에 없는 환경이다 보니...
가끔식 보안검열을 하면 지적을 받곤 했었습니다. 사실 대박 영창감인데... ㅋ 워낙 군대는 가라가 많아서리..ㅋㅋ
하지만 컴퓨터에서 비밀문서 편집을 해야만 하기때문에 특별한 보안지침이 있었습니다.
그것은 바로 자신의 컴퓨터에서 비밀문서를 취급할때는 인트라넷선을 꼭 뽑아놓고 사용하라는 지침이었습니다.
대대에서는 LAN선을 A와 B로 나누어 선택하여 쓸 수 있는 스위칭 장치를 구입하여 랜선을 껐다 켰다 하는 장치로 사용하였고,
그때 상당히 많은양을 구입한것으로 생각됩니다. 전국 비행대대가 거의 샀다고 들렸으니까요...

제 전공이 전공인지라, '그거 그냥 네트워크 사용안함으로 놓고 쓰면 될텐데...' 하는 생각을 많이 했었습니다.
하지만 입을 다물었습니다. 50여명이나 되는 장교들에게 그것을 가르쳐주기란... 미X짓이나 다름이 없었으니까요...ㅡㅡ;
대한민국 부사관, 장교들의 상당수는 병사가 할일을 절대 배워서 스스로 하려고 하지 않습니다. 시키죠... 편하게...ㅡㅡ;

하여튼 그때는 가르쳐주기도 힘들었고, 그 스위칭장치가 비록 얼마 하지 않았지만 왠지 혈세낭비같아 보여서 좀 비효율적이라는 생각이 많이 들었습니다. 그래서 생각한것이 소프트웨어를 하나 만들어서 배포하면 좋겠다는 생각을 해보았습니다.
물론 그시절엔 그런걸 구현할 수 있는 실력도 안되었으면서 그냥 막연한 생각만 했었습니다. 굉장히 간단할것 같은데 말이죠...

그러고 전역을 하고, 1년이 지나고 2년이 지난 2008년 10월쯤 문득 생각이 나서, 관련 자료를 찾아보았습니다.
그때 이 페이지를 보았습니다.

NIC 이름으로 활성/비활성 시키는 코드 : http://blog.naver.com/PostView.nhn?blogId=noirxeno&logNo=60053988997

그리고 더 찾아다니다가 또하나 발견했습니다.

Disable/Enable Network : http://www.codeguru.com/forum/showthread.php?t=419909

소스를 보니 역시 간단했습니다. 하지만 그시절엔 이 소스를 봤어도 못만들었을테지요... 하여튼 뿌듯했습니다.
한나절 끄적대서 프로그램을 만들고, 부대에 있는 X하사 형님에게 보내주고, 컴에 저장시켜 놓았다가...
요즘 블로그를 작성하면서 잘 정리하여 보관하고, 또 사람들과 공유하기 위하여 이 글을 쓰고 있습니다.

서론이 너무 길었습니다. ㅎㅎㅎ 본론으로 들어가죠.
먼저 소스코드입니다. 이 소스는 블로그에 올리려고 제가 쉽게 다시 뽑아낸 소스입니다.
소스 Copy & Paste 하셔서 BreakPoint찍어가면서 몇번만 실행해보시면 금방 이해하실 수 있을겁니다.
설명은 따로 안하겠습니다....

이 소스로 제작된 프로그램은 http://funnism.com/15 에서 다운받으실 수 있습니다.

#include
#include
#include
#include

using namespace std;

BOOL IsConnection();
int Connect();

int main()
{
    int hr = 0;

    if(IsConnection()){
        // 연결이 되어있는 상태입니다.
        cout << "현재 네트워크 카드의 드라이브는 사용중입니다." << endl;
        cout << "연결 해제합니다.";
    }else{
        // 연결이 되어있지 않으니 연결합니다.
        cout << "현재 네트워크 카드의 드라이브는 사용중지된 상태입니다." << endl;
        cout << "연결 합니다. : ";
    }
    hr = Connect();

    if(hr==0){
        cout << "네트워크 카드의 연결이 해제되었습니다." << endl;
    }else if(hr == 1){
        cout << "네트워크 카드가 연결되었습니다." << endl;
    }
    return 0;
}

BOOL IsConnection(){
    int status = FALSE; //1:connect, 0:disconnect
    HRESULT result = 0;

    CoInitialize(0);

    INetConnectionManager *pMan = 0;
    HRESULT hres = CoCreateInstance(CLSID_ConnectionManager,
                                                        0,
                                                        CLSCTX_ALL,
                                                        __uuidof(INetConnectionManager),
                                                        (void**)&pMan);

    if (SUCCEEDED(hres))
    {
        IEnumNetConnection *pEnum = 0;
        hres = pMan->EnumConnections(NCME_DEFAULT, &pEnum);
        if (SUCCEEDED(hres))
        {
            INetConnection *pCon = 0;
            ULONG count;
            while (pEnum->Next(1, &pCon, &count) == S_OK )
            {
                NETCON_PROPERTIES *pProps = 0;
                hres = pCon->GetProperties(&pProps);
                if (SUCCEEDED(hres))
                {
                    if (pProps->Status == NCS_DISCONNECTED){
                        status = FALSE;
                    }
                    else if (pProps->Status == NCS_CONNECTED){
                        status = TRUE;
                    }

                    if (pProps)
                    {
                        CoTaskMemFree(pProps->pszwName);
                        CoTaskMemFree(pProps->pszwDeviceName);
                        CoTaskMemFree(pProps);
                    }
                }
                pCon->Release();
            }
            pEnum->Release();
        }
        pMan->Release();
    }

    CoUninitialize();
    return status;
}

int Connect(){
    int status = 0; //1:connect, 0:disconnect
    HRESULT result = 0;

    CoInitialize(0);

    INetConnectionManager *pMan = 0;
    HRESULT hres = CoCreateInstance(CLSID_ConnectionManager,
                                                        0,
                                                        CLSCTX_ALL,
                                                        __uuidof(INetConnectionManager),
                                                        (void**)&pMan);

    if (SUCCEEDED(hres))
    {
        IEnumNetConnection *pEnum = 0;
        hres = pMan->EnumConnections(NCME_DEFAULT, &pEnum);
        if (SUCCEEDED(hres))
        {
            INetConnection *pCon = 0;
            ULONG count;
            while (pEnum->Next(1, &pCon, &count) == S_OK)
            {
                NETCON_PROPERTIES *pProps = 0;
                hres = pCon->GetProperties(&pProps);
                if (SUCCEEDED(hres))
                {
                    if (pProps->Status == NCS_DISCONNECTED){
                        result = pCon->Connect();
                        status = 1;
                    }
                    else if (pProps->Status == NCS_CONNECTED){
                        result = pCon->Disconnect();
                        status = 0;
                    }

                    if (pProps)
                    {
                        CoTaskMemFree(pProps->pszwName);
                        CoTaskMemFree(pProps->pszwDeviceName);
                        CoTaskMemFree(pProps);
                    }
                }
                pCon->Release();
            }
            pEnum->Release();
        }
        pMan->Release();
    }

    CoUninitialize();
    return status;
}
저작자 표시 비영리 변경 금지
Posted by 태발이
2009/01/24 19:01

MFC 클래스 계층도는 MSDN에서 "hierarchy chart" 라고 검색하면 바로 확인해볼 수 있습니다.

그래도 혹시나 빠르게 확인해보고 싶으신 분들을 위해 올려놓습니다.

MFC 9.0은 "Visual Studio 2008"에 새롭게 업데이트된 버젼입니다.

저는 이 그림을 프린트해서 책상앞에 붙여놓았습니다. 항상 쳐다보며 숙지해야겠네요....^^

저작자 표시 비영리 변경 금지
Posted by 태발이
2009/01/24 18:37


표준 MFC의 클래스

1. 어플리케이션(CWinApp)

   - 프로그램을 초기화한다.

   - 메시지 루프를 포함하고 있다.

   - CDocTemplate을 생성하여 메인 프레임, 뷰, 도큐먼트 객체와 리소스를 유기적으로 결합하고 관리한다.


2. 메인프레임(CFrameWnd)

   - 프로그램의 메인 윈도우를 관리한다.

   - 메뉴, 툴바, 상태바와 같은 비클라이언트 영역을 관리한다.


3. 뷰(CView)

   - 클라이언트 영역인 뷰 윈도우를 관리한다.

   - 도큐먼트의 데이터를 화면이나 프린터 등에 디스플레이한다.


4. 도큐먼트(CDocument)

   - 뷰에 출력되는 데이터를 보관한다.

   - 디스크에 데이터 저장 및 로드를 한다.

저작자 표시 비영리 변경 금지
Posted by 태발이
2009/01/15 17:35
먼저 IME를 사용하려면 프로젝트에 Imm32.lib를 추가하고, imm.h를 인클루드 해야한다.



IME 메시지

WM_IME_STARTCOMPOSITION 
    IME가 조립 문자열을 만들기 직전에 보냄. WPARAM, LPARAM의 값은 없음. 이 메시지를 DefWindowProc으로
    보내지 않으면 조립윈도우가 나타나지 않는다.

WM_IME_ENDCOMPOSITION
    조립이 끝났다는 통지 메시지. 인수와 리턴값 없음. 커스텀 IME 윈도우를 작성하지 않는다면 무시해도 무방함.

WM_IME_COMPOSITION
    조립 상태가 변경될때마다 보내진다. 
    WPARAM - 조립중의 문자의 코드가 전달, 이 코드는 2byte의 DBCS문자로 조립중인 중간 문자코드이다.
    LPARAM - 조립상태가 어떻게 변경되었는지, 이 문자를 어떻게 처리해야 하는지를 나타내는 플래그의 집합.
                    한글의 경우 다음 두 플래그가 특히 중요함.
                        GCS_COMPSTR : 아직 문자를 조립중이라는 뜻, 즉 아직 한 음절이 완성되지는 않았음.
                        GCS_RESULTSTR : 한 음절을 완전히 조립했다는 뜻.
                    이 플래그들이 있는지 살펴보면 문자가 완성된 것인지, 조립중인지 알 수 있음.

WM_IME_CHAR
    문자 하나가 완성되었을때 보내짐.
    WPARAM - 완성된 문자의 코드가 전달. 1byte만 전달되는 WM_CHAR과는 달리 DBCS일 수 있음.
                     (단, 유니코드 윈도우에서는 WM_CHAR, WM_IME_CHAR 모두 2byte이다.)
    이 메시지를 무시하면 한글 한 문자에 대해 WM_CHAR 메시지를 두번 받게 된다.

WM_IME_SETCONTEXT
    응용프로그램이 활성/비활성화될 때 보내진다. WPARAM이 TRUE이면 활성, FALSE이면 비활성화 되었다는 뜻이다.

WM_IME_NOTIFY
    IME 윈도우가 변경되었다는 통지 메시지이다. WPARAM으로 어떤 변경인지 통보됨.한글 입력, 영문 입력모드를
    변경할 때도 이 메시지가 전달된다.



Input Context 생성, 해제

Input Context(입력 컨텍스트) : IME가 내부적으로 사용하는 구조체이며 조립 문자열, 변환모드, IME 윈도우의 위치 등 IME의 현재 상태에 대한 정보들이 저장됨.


Input Context의 핸들을 얻는 함수

HIMC ImmGetContext(void);
BOOL ImmReleaseContext(HWND hWnd, HIMC hIMC);
 
Input Context를 조작하는 함수

BOOL ImmGetConversionStatus(HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence);
BOOL ImmSetConversionStatus(HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence);

    입력모드를 한글로 변환하고 싶으면
ImmSetConversionStatus(hImc, IME_CMODE_NATIVE, IME_SMODE_NONE);

    입력모드를 영어로 변환하고 싶으면
ImmSetConversionStatus(hImc, 0, IME_SMODE_NONE);
를 호출하면 된다.

    하지만 시스템이 만드는 Default Input Context는 스레드 내의 모든 윈도우가 공유하기 때문에 한글이나 영문으로 변경시
    모든 입력모드가 통일되게 변경된다. 만약 각각의 컨트롤에서 다른 입력모드를 주고 싶다면 윈도우별로 InputContext를
    생성, 해제하여 연결시키면 된다.


Input Context를 생성, 해제하는 함수

// InputContext를 위한 메모리를 할당하고, 그 핸들을 리턴
HIMC ImmCreateContext(void);

// 특정 윈도우와 연결
HIMC ImmAssociateContext(HWND hWnd, HIMC hIMC);

// InputContext를 메모리에서 해제
BOOL ImmDestroyContext(HIMC hIMC);

    InputContext를 생성, 해제할 경우에는 Pen, Brush를 생성, 해제할때와 같은 방법으로 한다.
저작자 표시 비영리 변경 금지
Posted by 태발이
2009/01/09 16:56
많은 윈도우즈 프로그래머들은 전설적인 마이크로소프트 프로그래머인 찰스 시모니(Charles Simonyi)를 기리는 뜻으로 '헝가리안 표기법(Hungarian notation)'이라 하는 변수 명명법을 사용한다. 원리를 아주 간단히 말하면, 변수 이름이 변수의 데이터 타입을 나타내는 소문자들로 시작하는 것이다.

 접두사 데이터 타입 
 c char 또는 WCHAR 또는 TCHAR 
 by  BYTE(unsigned char)
 n  short
 i  int
 x, y  int(x, y 좌표로 사용)
 cx, cy  int(x, y 길이로 사용); c는 'count'를 의미
 b or f  BOOL(int); f는 'flag'를 의미
 w  WORD(unsigned short)
 l  LONG(long)
 dw  DWORD(unsigned long)
 fn  function
 s  string
 sz  string terminated by 0 character
 h  handle
 p  pointer

출처 : 찰스페졸드의 Programming Windows 5th Edition p.81~82

보통 프로그래밍을 공부하는 초보자나 학생들은 변수명을 자기 멋대로 붙여 쓰는 경우가 많다. 내 경우에도 a, aa, i, a1... 뭐 이런식으로 쓸때가 많았는데... 남의 소스코드를 볼때나 나중에 필드에 나가서 프로그래밍을 할때는 변수 명명법을 문서화시킨다던지 일정한 규칙을 정해놓고 네이밍을 해서 써야 하므로... 지금부터라도 변수이름을 위와같은 규칙으로 지정하여 쓰는 습관을 들이는것이 좋겠다.
저작자 표시 비영리 변경 금지
Posted by 태발이