'MFC'에 해당되는 글 56건

  1. 2011.04.14 Visual Studio 2010 Service Pack 1에 대한 모든 것
  2. 2011.04.14 Visual Studio 2010 Service Pack 1에 대한 모든 것
  3. 2011.01.06 [이벤트] 제 2회 Visual Studio Ultimate 멤버십 세미나
  4. 2009.10.20 [업데이트] ActiveX 권한 상승에 대한 일반적인 이야기와 솔루션들 (5)
  5. 2008.08.13 Visual Studio 2008 및 .NET Framework 3.5 SP1 발표 (2)
  6. 2002.08.09 #50. Serialization과 관련된 MFC의 3대 매크로 함수
  7. 2002.08.01 #49. CImage 클래스
  8. 2002.07.24 #48. Serialization이 가능하도록 CObject 클래스 상속 (원제: .NET에서의 CObject 클래스 상속)
  9. 2002.07.19 #47. Managed Extensions for C++의 새로운 문법들
  10. 2002.07.18 #46. Managed Extensions
  11. 2002.07.01 #45. 어플리케이션 디버깅 (Quick Watch, Watch)
  12. 2002.07.01 #44. 어플리케이션 디버깅 (Break Point)
  13. 2002.07.01 #43. 어플리케이션 디버깅 (Call Stack)
  14. 2002.06.25 #42. 서브 시스템의 비밀
  15. 2002.06.25 #39. 콘솔 어플리케이션에서의 MFC 사용
  16. 2002.06.20 #41. Windows NT에서의 디버그
  17. 2002.06.20 #40. MFC에서 콘솔 명령어 처리하기
  18. 2002.06.16 #38. 일관성있는 클래스/리소스 배치
  19. 2002.06.16 #37. 왜 데이터 타입 클래스를 만들때 CObject에서 상속받는가?
  20. 2002.06.16 #36. _T("") 매크로에 대하여
  21. 2002.06.13 #35. Microsoft Windows 정보 대화 상자 사용하기
  22. 2002.06.11 #34. MDI vs. SDI
  23. 2002.06.08 #33. HTTP 프로토콜로부터 HTML 파일 가져오기
  24. 2002.06.08 #32. Windows 공용 DLL에서의 데이터 타입
  25. 2002.06.08 #31. MFC 전용 확장 DLL의 작성
  26. 2002.06.04 #30. 클래스에 대한 정보를 프로그램상에서 활용하기
  27. 2002.05.23 #29. 메시지 스트림 가로채기
  28. 2002.05.17 #28. Dynamic Link Library의 사용법
  29. 2002.05.15 #27. CObArray 클래스
  30. 2002.05.10 #26. WYSIWIG (What You See Is What You Get)의 구현
Visual Studio2011. 4. 14. 17:00

안녕하세요. 오랫만에 블로그에 글을 올립니다. 지난번 Visual Studio Camp에서 옴니버스 형식의 세미나로 Visual Studio 2010 Service Pack 1에 대하여 말씀을 드렸던 세션이 있는데, 발표 자료와 더불어서 Visual Studio 2010 SP1에 대한 간략한 소개를 위하여 글을 씁니다.


Visual Studio의 새 도움말 시스템

Visual Studio 2010 RTM 버전부터는 새로운 형태의 도움말 시스템이 도입되는데, 로컬 웹 서버를 통하여 도움말 컨텐츠가 제공되는 방식으로 이전의 Visual Studio 2005와 Visual Studio 2008에서 제공되던 방식과 다르게 제공됩니다. Visual Studio 2005와 Visual Studio 2008의 경우 자체 URI Scheme을 Windows Registry에 등록하고 이를 Internet Explorer를 통하여 탐색할 수 있도록 확장하는 방식이었습니다. 그러나 새로운 도움말 컬렉션을 추가하거나 삭제하는 과정에서 시스템 성능에 따라 재배열 시간이 상당히 오래 걸리는 문제가 있어 불편한 점도 있었습니다. 이러한 방식 대신 더 단순하지만 더 유연한 방식으로 바꾸게 된 듯 합니다.

그렇지만 이전 버전에서 제공되던 색인, 검색 기능 등이 웹 사이트 형식으로 바뀌면서 이전에 사용했던 기능들이 사라져서 아쉬운 점도 있었는데 이번 Service Pack 1에서는 다시 Help Browser Software가 부활했습니다. 그래서 로컬 웹 서버로 컨텐츠를 보여주는 것은 동일하지만 Visual Studio를 통해서 컨텐츠를 탐색하면 Help Browser가 별도로 나타납니다.

그리고 이번 도움말 시스템에서의 백미는 인터넷을 통한 업데이트가 가능해졌다는 점입니다. 실제로 설치한 적이 없는 제품이라 할지라도, 그리고 DVD를 통해서만 설치할 수 있는 전체 버전의 MSDN 안에서만 제공되던 컨텐츠까지도 인터넷을 통하여 항상 최신 버전을 다운로드받아 로컬 도움말 컬렉션에 추가하거나 필요하지 않으면 삭제할 수 있습니다.

Silverlight 4에 대한 지원 추가

Visual Studio 2010 SP1을 설치하면 별도로 Silverlight 4에 대한 Tools for Visual Studio를 추가 설치할 필요가 없습니다. Silverlight 4부터는 이전의 WPF보다 작지만 웹이 아닌 데스크탑 및 오프라인 환경에서 잘 동작하는 응용프로그램을 제작할 수 있는 기능이 더 완벽하게 제공됩니다. 이러한 기술 전반은 권한 상승이 적용된 실버라이트 응용프로그램에서 가능한 것이며, 여기에는 파일 입출력이나 로컬 COM 컴포넌트와 연계하는 방안이 포함되어있습니다. 아래의 예제는 권한 상승이 적용된 Silverlight 4 기반 응용프로그램 샘플의 소스 코드이며, 사용자 프로필 디렉터리 내의 "내 그림" 폴더에 있는 이미지들을 열거하고 뷰어를 통하여 보여주는 예제입니다.



위 프로그램의 소스 코드 중 파일 입출력에 대한 소스 코드를 실제로 발췌하면 다음과 같습니다.

private void UpdateFileList()
{
    string targetPath = Environment.GetFolderPath(
        Environment.SpecialFolder.MyPictures);
 
    List<object> content = new List<object>();
    foreach (string eachFile in Directory.EnumerateFiles(targetPath))
    {
        switch (System.IO.Path.GetExtension(eachFile).ToLower())
        {
            case ".jpg":
            case ".jpeg":
            case ".png":
                break;
 
            default:
                continue;
        }
 
        content.Add(eachFile);
    }
    this.fileList.ItemsSource = content;
}
Visual Studio 2010 SP1을 설치한 후 Silverlight 프로젝트를 생성하려고 하면 다음과 같이 대화 상자가 나타나는데 이 때 Silverlight 4를 사용하도록 지정하면 사용이 가능합니다.

IIS Express 7.5에 대한 지원 추가

Visual Studio 2005부터는 Cassini Web Server라고 불리던 ASP.NET Development Server를 통하여 전체 버전의 IIS가 없어도 쉽게 ASP.NET 응용프로그램을 테스트할 수 있는 환경이 제공되었습니다. 그러나 Visual Studio 2008의 등장과 더불어 IIS 역시 대폭 업그레이드되어 Windows Server 2008부터는 완전히 새로워진 아키텍처를 기반으로 하는 IIS 7이 등장하게 됩니다. 이에 따라, 어느 정도 호환성을 보장하기는 하지만 이전의 IIS와는 많이 달라졌기 때문에 Cassini Web Server 만으로는 테스트가 어려운 점이 많았습니다. 통합 IDE의 이점도 확보하고, 전체 버전의 IIS를 사용하지 않으면서도 충분히 모든 기능을 점검해볼 수 있는 방향으로 가기 위하여 IIS Express가 등장하게 됩니다.

IIS Express를 사용하는 것은 실제 IIS를 사용하는 것과 비교했을 때 다음과 같은 장점이 있습니다.

  • ASP.NET Development Server와는 달리 FastCGI 모듈을 호스팅할 수 있으므로 PHP와 같은 FastCGI 지원 웹 언어들을 같은 환경에서 동시에 테스트할 수 있습니다.
  • 웹 프로젝트에서 IIS를 사용하도록 지정한 경우, 관리자 권한을 얻을 수 없는 다른 컴퓨터에서는 웹 프로젝트를 열 수 없는 문제점이 있었으나 IIS Express를 사용하도록 하면 이런 제약이 없습니다.
  • IIS Hosted Core를 사용하므로 전체 버전의 IIS가 없어도 상관이 없으며, IIS Express가 설치되어있지 않은 경우 Visual Studio가 자동으로 이를 감지하여 Web Platform Installer를 호출하여 IIS Express가 설치될 수 있도록 해줍니다.
  • 개별 프로세스 형태로 실행되므로 여러 사람이 사용하는 컴퓨터에서도 시스템 설정을 편집하는 일 없이 안전하게 실행할 수 있습니다.

 

HTML 5와 CSS 3에 대한 문법 검증 지원

Visual Studio 2010 SP1 및 Visual Web Developer 2010 Express SP1을 설치하면 HTML 5, XHTML 5 및 CSS 3에 대한 지원이 기본으로 내장되어있어 정확한 코딩이 가능합니다.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>HTML5 Test</title>
    <link type="text/css" rel="Stylesheet" href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.10/themes/redmond/jquery-ui.css" /> 
    <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.js"></script>
    <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.10/jquery-ui.js"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            $('#test').dialog({ show: "drop", hide: "drop", width: "auto", height: "auto", title: "html 5 rocks!" }).show();
        });
    </script>
</head>
<body>
    <div id="test">
        <video src="demo.mp4" width="700" height="500" id="testVideo" autoplay="autoplay">
            <strong>Your web browser does not support video element.</strong>
        </video>
    </div>
</body>
</html>



위의 그림과 같이 검사할 문법을 지정하여 프로그래밍하면 꼭 지정해야 할 프로퍼티를 검사하여 경고를 띄우거나, 프로퍼티에 포함되어야 할 값의 유형을 자동으로 유추해주어 규칙을 몰라서 잘못 코딩할 가능성을 예방해 줍니다.

그 외에 눈여겨 볼만한 것들

Visual Studio 역시 최근에 급격한 변화를 맞이하고 있습니다. 빠르게 변화하는 기술을 수용하기 위해서 Internet Explorer의 런칭 주기가 짧아진 것과 비슷하게, Visual Studio 역시 자주 새로운 형태의 도구와 프레임워크를 업데이트하고 있으며, 이러한 노력의 일환으로 Express Edition의 가치가 더 높아지고 있습니다.

대표적으로 Visual Studio LightSwitch와 Visual Web Developer Express Edition, 그리고 Visual Studio for Windows Phone 7이 그 예시입니다. 전체 버전의 Visual Studio 제품 구성을 바꾸지 않고 안전하게 테스트해볼 수 있는 방법으로서도, 그리고 실무 개발 환경에서도 유용하게 쓰일 수 있습니다.

그러나 서비스 팩 출시와 더불어서 Express Edition의 경우 한 박자 정도 업데이트가 늦어지는 편입니다. 이 때문에, 먼저 설치한 서비스 팩과 나중에 설치한 RTM 버전의 Express Edition 사이의 버전 차로 인한 충돌 문제가 이슈가 되었던적이 있는데, 이번 버전부터는 그러한 상황이 있을 경우 Visual Studio가 시작되기 전에 해당 문제점을 사용자에게 정확히 알려줍니다. 그 외에, 다양한 도구와 런타임에서 기능 및 성능 향상이 있었습니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual Studio2011. 4. 14. 10:36

안녕하세요. 오랫만에 블로그에 글을 올립니다. 지난번 Visual Studio Camp에서 옴니버스 형식의 세미나로 Visual Studio 2010 Service Pack 1에 대하여 말씀을 드렸던 세션이 있는데, 발표 자료와 더불어서 Visual Studio 2010 SP1에 대한 간략한 소개를 위하여 글을 씁니다.


Visual Studio의 새 도움말 시스템

Visual Studio 2010 RTM 버전부터는 새로운 형태의 도움말 시스템이 도입되는데, 로컬 웹 서버를 통하여 도움말 컨텐츠가 제공되는 방식으로 이전의 Visual Studio 2005와 Visual Studio 2008에서 제공되던 방식과 다르게 제공됩니다. Visual Studio 2005와 Visual Studio 2008의 경우 자체 URI Scheme을 Windows Registry에 등록하고 이를 Internet Explorer를 통하여 탐색할 수 있도록 확장하는 방식이었습니다. 그러나 새로운 도움말 컬렉션을 추가하거나 삭제하는 과정에서 시스템 성능에 따라 재배열 시간이 상당히 오래 걸리는 문제가 있어 불편한 점도 있었습니다. 이러한 방식 대신 더 단순하지만 더 유연한 방식으로 바꾸게 된 듯 합니다.

그렇지만 이전 버전에서 제공되던 색인, 검색 기능 등이 웹 사이트 형식으로 바뀌면서 이전에 사용했던 기능들이 사라져서 아쉬운 점도 있었는데 이번 Service Pack 1에서는 다시 Help Browser Software가 부활했습니다. 그래서 로컬 웹 서버로 컨텐츠를 보여주는 것은 동일하지만 Visual Studio를 통해서 컨텐츠를 탐색하면 Help Browser가 별도로 나타납니다.

그리고 이번 도움말 시스템에서의 백미는 인터넷을 통한 업데이트가 가능해졌다는 점입니다. 실제로 설치한 적이 없는 제품이라 할지라도, 그리고 DVD를 통해서만 설치할 수 있는 전체 버전의 MSDN 안에서만 제공되던 컨텐츠까지도 인터넷을 통하여 항상 최신 버전을 다운로드받아 로컬 도움말 컬렉션에 추가하거나 필요하지 않으면 삭제할 수 있습니다.



Silverlight 4에 대한 지원 추가

Visual Studio 2010 SP1을 설치하면 별도로 Silverlight 4에 대한 Tools for Visual Studio를 추가 설치할 필요가 없습니다. Silverlight 4부터는 이전의 WPF보다 작지만 웹이 아닌 데스크탑 및 오프라인 환경에서 잘 동작하는 응용프로그램을 제작할 수 있는 기능이 더 완벽하게 제공됩니다. 이러한 기술 전반은 권한 상승이 적용된 실버라이트 응용프로그램에서 가능한 것이며, 여기에는 파일 입출력이나 로컬 COM 컴포넌트와 연계하는 방안이 포함되어있습니다. 아래의 예제는 권한 상승이 적용된 Silverlight 4 기반 응용프로그램 샘플의 소스 코드이며, 사용자 프로필 디렉터리 내의 "내 그림" 폴더에 있는 이미지들을 열거하고 뷰어를 통하여 보여주는 예제입니다.



위 프로그램의 소스 코드 중 파일 입출력에 대한 소스 코드를 실제로 발췌하면 다음과 같습니다.

private void UpdateFileList()
{
    string targetPath = Environment.GetFolderPath(
        Environment.SpecialFolder.MyPictures);
 
    List<object> content = new List<object>();
    foreach (string eachFile in Directory.EnumerateFiles(targetPath))
    {
        switch (System.IO.Path.GetExtension(eachFile).ToLower())
        {
            case ".jpg":
            case ".jpeg":
            case ".png":
                break;
 
            default:
                continue;
        }
 
        content.Add(eachFile);
    }
    this.fileList.ItemsSource = content;
}
Visual Studio 2010 SP1을 설치한 후 Silverlight 프로젝트를 생성하려고 하면 다음과 같이 대화 상자가 나타나는데 이 때 Silverlight 4를 사용하도록 지정하면 사용이 가능합니다.


IIS Express 7.5에 대한 지원 추가

Visual Studio 2005부터는 Cassini Web Server라고 불리던 ASP.NET Development Server를 통하여 전체 버전의 IIS가 없어도 쉽게 ASP.NET 응용프로그램을 테스트할 수 있는 환경이 제공되었습니다. 그러나 Visual Studio 2008의 등장과 더불어 IIS 역시 대폭 업그레이드되어 Windows Server 2008부터는 완전히 새로워진 아키텍처를 기반으로 하는 IIS 7이 등장하게 됩니다. 이에 따라, 어느 정도 호환성을 보장하기는 하지만 이전의 IIS와는 많이 달라졌기 때문에 Cassini Web Server 만으로는 테스트가 어려운 점이 많았습니다. 통합 IDE의 이점도 확보하고, 전체 버전의 IIS를 사용하지 않으면서도 충분히 모든 기능을 점검해볼 수 있는 방향으로 가기 위하여 IIS Express가 등장하게 됩니다.

IIS Express를 사용하는 것은 실제 IIS를 사용하는 것과 비교했을 때 다음과 같은 장점이 있습니다.

  • ASP.NET Development Server와는 달리 FastCGI 모듈을 호스팅할 수 있으므로 PHP와 같은 FastCGI 지원 웹 언어들을 같은 환경에서 동시에 테스트할 수 있습니다.
  • 웹 프로젝트에서 IIS를 사용하도록 지정한 경우, 관리자 권한을 얻을 수 없는 다른 컴퓨터에서는 웹 프로젝트를 열 수 없는 문제점이 있었으나 IIS Express를 사용하도록 하면 이런 제약이 없습니다.
  • IIS Hosted Core를 사용하므로 전체 버전의 IIS가 없어도 상관이 없으며, IIS Express가 설치되어있지 않은 경우 Visual Studio가 자동으로 이를 감지하여 Web Platform Installer를 호출하여 IIS Express가 설치될 수 있도록 해줍니다.
  • 개별 프로세스 형태로 실행되므로 여러 사람이 사용하는 컴퓨터에서도 시스템 설정을 편집하는 일 없이 안전하게 실행할 수 있습니다.

HTML 5와 CSS 3에 대한 문법 검증 지원

Visual Studio 2010 SP1 및 Visual Web Developer 2010 Express SP1을 설치하면 HTML 5, XHTML 5 및 CSS 3에 대한 지원이 기본으로 내장되어있어 정확한 코딩이 가능합니다.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>HTML5 Test</title>
    <link type="text/css" rel="Stylesheet" href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.10/themes/redmond/jquery-ui.css" /> 
    <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.js"></script>
    <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.10/jquery-ui.js"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            $('#test').dialog({ show: "drop", hide: "drop", width: "auto", height: "auto", title: "html 5 rocks!" }).show();
        });
    </script>
</head>
<body>
    <div id="test">
        <video src="demo.mp4" width="700" height="500" id="testVideo" autoplay="autoplay">
            <strong>Your web browser does not support video element.</strong>
        </video>
    </div>
</body>
</html>



위의 그림과 같이 검사할 문법을 지정하여 프로그래밍하면 꼭 지정해야 할 프로퍼티를 검사하여 경고를 띄우거나, 프로퍼티에 포함되어야 할 값의 유형을 자동으로 유추해주어 규칙을 몰라서 잘못 코딩할 가능성을 예방해 줍니다.

그 외에 눈여겨 볼만한 것들

Visual Studio 역시 최근에 급격한 변화를 맞이하고 있습니다. 빠르게 변화하는 기술을 수용하기 위해서 Internet Explorer의 런칭 주기가 짧아진 것과 비슷하게, Visual Studio 역시 자주 새로운 형태의 도구와 프레임워크를 업데이트하고 있으며, 이러한 노력의 일환으로 Express Edition의 가치가 더 높아지고 있습니다.

대표적으로 Visual Studio LightSwitch와 Visual Web Developer Express Edition, 그리고 Visual Studio for Windows Phone 7이 그 예시입니다. 전체 버전의 Visual Studio 제품 구성을 바꾸지 않고 안전하게 테스트해볼 수 있는 방법으로서도, 그리고 실무 개발 환경에서도 유용하게 쓰일 수 있습니다.

그러나 서비스 팩 출시와 더불어서 Express Edition의 경우 한 박자 정도 업데이트가 늦어지는 편입니다. 이 때문에, 먼저 설치한 서비스 팩과 나중에 설치한 RTM 버전의 Express Edition 사이의 버전 차로 인한 충돌 문제가 이슈가 되었던적이 있는데, 이번 버전부터는 그러한 상황이 있을 경우 Visual Studio가 시작되기 전에 해당 문제점을 사용자에게 정확히 알려줍니다. 그 외에, 다양한 도구와 런타임에서 기능 및 성능 향상이 있었습니다.
Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

이벤트2011. 1. 6. 01:53
Visual Studio 2010 Ultimate 에디션과 떠나는 여행, 그 두번째 : 
소프트웨어 품질관리 및 무결점 소프트웨어의 중요성
일시 : 2011. 01. 26(수) 14:00~18:10 | 장소 : 한국 마이크로소프트 Win room(5F)

Visual Studio 2010 Ultimate 에디션 사용자 여러분 새해 복 많이 받으시길 바랍니다.
2010
년 12월에 예정하였던 제2회 Visual Studio Ultimate 멤버십 세미나를 2011년 1월 26일에 개최합니다.

본 프로그램은 국내 300여개 Visual Studio 2010 Ultimate 을 적법하게 구매하시거나 보유하고 계신 고객사의 개발팀장 여러분들을만을 
대상으로 하는 프로그램으로 여러분들에게 Visual Studio 2010 Ultimate 에디션을 200% 활용하여 애플리케이션 개발의 혁신을 이루실 수 
있도록 도와드리는 특별한 프로그램입니다.

지난 2010년 10월 13일 제 1회 정기 세미나에 이어, 2011년 1월 26일 제 2회 Visual Studio 2010 Ultimate 멤버십 세미나를 개최합니다.
본 두번째 세미나에서는 요즘 소프트웨어 개발에서 가장 뜨거운 화두로 떠오르고 있는 소프트웨어 품질에 대한 이야기를 해보고자 합니다. 
소프트웨어 품질의 관리가 여러분들의 비즈니스성공에 얼마나 중요한 요소인지를 알아 보고, Visual Studio 2010 Ultimate 의 IntelliTrace 를 
활용하여 무결점 소프트웨어 개발을 위한 혁신적인 디버깅 방법, Lab Management 를 활용한 효율적인 소프트웨어 품질관리, 그리고 SDL 과 
더욱 강력한 소프트웨어 품질관리를 위해 발표된 Visual Studio Ultimate Feature Pack 등을 알려드리는 시간을 가지려고 합니다.

바쁘시겠지만 꼭 참석하시어 Visual Studio 2010 최상위 에디션인 Ultimate 에디션 사용고객으로서 최고의 가치를 누리실 수 있는 방법을 
알아 보시기 바랍니다. 2011년 1월 26일, Visual Studio Ultimate 멤버십 고객 여러분들의 많은 참석 부탁드립니다.

여러분들의 개발능률과 애플리케이션 개발방법의 혁신을 이루어 드릴
Visual Studio 2010 Ultimate 에디션과의 그 두번째 여행, 2011년 1월 26일 함께 떠날 수 있기를 바랍니다.

14:00-14:30 등록  
14:30-14:35 인사말 황재현 부장, 
한국마이크로소프트
14:35-14:55 Visual Studio 2010 Ultimate 업데이트 1 : 
마이크로소프트 Security Development Lifecycle 소개
강성재 차장, 
한국마이크로소프트
14:55-14:15 Visual Studio 2010 Ultimate 업데이트2 : 
Visual Studio 2010 Ultimate 에 보다 강력한 기능을 더해주는 
Visual Studio 2010 Feature Pack 2 와 SDK 소개
강성재 차장, 
한국마이크로소프트
15:15-15:25 휴식  
15:25-16:15 Keynote : 효과적인 소프트웨어 품질 관리의 중요성 신경준 MVP, 
안철수 연구소
16:15-16:25 휴식  
16:25-17:15 Visual Studio 2010 Ultimate 유저만을 위한 디버깅 전문 사립탐정
- IntelliTrace
강보람 MVP
17:15-18:05 테스트와 가상화의 만남 - 테스트 가상화(Lab Management) 엄준일 MVP, 
NC SOFT
18:05-18:10 경품 추첨 및 맺음말  
  • 본 행사는 Visual Studio 2010 Ultimate 를 보유하신 VIP 고객사만을 위한 행사입니다.
  • 참석하신 분들 중 추첨을 통하여 푸짐한 경품을 드립니다.
  • 참석하신 모든 분들께 소정의 기념품을 드립니다.
  • 좌석이 한정되어 있으니, 반드시 사전 등록해 주시기 바랍니다.

행사 등록사무국 02) 598-9898 rgst@neodigm.com
Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2009. 10. 20. 10:57

최근 고객사의 요청으로 ActiveX 컨트롤 하나를 유지보수하고 있습니다. ActiveX 컨트롤에서 탈피하려는 추세가 있지만, 별 다른 대안이 없어서 ActiveX 컨트롤을 유지보수해야 하는 경우도 아직 우리나라에서는 상당히 많은것 같습니다.

 

Internet Explorer 7.0부터는 보호 모드라는 개념이 새로 소개되었습니다. 보호 모드란, 일종의 Sand-box 개념으로 기존과 같이 현재 로그온한 사용자의 권한을 그대로 물려받아 무분별하게 실행되는 것을 방어하는 안전 장치입니다. Windows XP와는 달리 Windows Vista부터는 일반 사용자를 단순히 관리자로 분류하지 않고, UAC를 통하여 작업에 대해 허가/거절 여부를 정할 수 있게 하였습니다.

 

우리가 권한 상승이라고 이야기하는 기능은 사실 권한 상승을 사용자에게 요청하는 것입니다. 이러한 권한 상승 요청을 구현하기 위하여 이제까지 참고할 수 있는 보편적인 리소스는 EXE 파일과 함께 매니페스트 파일을 배포하는 것이 대표적인 것이었습니다. 그리고 ActiveX 컨트롤의 경우 Elevation Moniker를 통하여 권한 할당을 받는 것이 대표적입니다.

 

ActiveX 컨트롤에서 어떻게 권한 상승을 구현할 수 있는지에 대하여 잘 정리한 권용휘 MVP님의 아티클을 참고하시면 어떻게 권한 상승이 이루어지고 관리될 수 있는지에 대한 컨셉을 확인하실 수 있습니다. (http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNO=20&no=7669) 저는 권용휘 MVP님의 아티클 위에 몇 가지 내용을 더 첨언해보고자 합니다.

 

1. Visual C++ 6.0 (SP6)에서의 권한 상승 구현

 

놀랍게도, 그리고 안타깝게도, Visual C++ 6.0 개발 도구를 업그레이드하지 못하는 이슈는 도처에 널려있습니다. 기존에 개발되어있던 소프트웨어나 라이브러리가 특정 문자 세트에 완벽하게 맞추어져있지만, 업그레이드할 수 없을만한 이슈 (개발 업체의 부도 - 또는 - 계약 해지 / 담당자의 연락 두절과 같은)로 인하여, 올해부터는 더 이상 일체의 기술 지원을 받을 수 없는 (서비스 팩 다운로드도 MS 공식 홈페이지에서는 더이상 받으실 수 없습니다.) 그런 개발 플랫폼위에서 고군분투해야 하는 상황은 생각보다 자주 있습니다.

 

사실 권한 상승을 제대로 프로그래밍하려면 Windows Vista나 Windows 7 SDK가 필요합니다. 하지만 이들 SDK의 코드를 가져다 사용하려면 개발 도구를 Visual C++ 2005나 2008로 업그레이드할 필요가 있습니다. 하지만 개발 도구나 Windows SDK를 설치하지 않고 간단히 적용할 수 있다고 소개된 방법은 다행히 Visual C++ 6.0에서 온전하게 동작합니다.

 

typedef struct tagBIND_OPTS3 : tagBIND_OPTS2 {
 HWND hwnd;
} BIND_OPTS3, *LPBIND_OPTS3;

위의 코드를 자주 사용하는 헤더에 선언해두면 권한 상승을 위하여 호출하는 CoGetObject에 정확히 바인딩할 수 있습니다. 그리고, 아래의 두 함수를 이용하여, 권한 상승을 지원하는 운영 체제 (Windows Vista 이상의 운영 체제)를 식별하고 실제로 객체를 생성할 수 있습니다.

 

HRESULT CoCreateInstanceAsAdmin(HWND hwnd, REFCLSID rclsid, REFIID riid, OUT void ** ppv)
{
 BIND_OPTS3 bo;
 OLECHAR wszCLSID[50];
 OLECHAR wszMonikerName[300];
 const int CHARS_IN_GUID = 39;

 StringFromGUID2(rclsid, wszCLSID, CHARS_IN_GUID);
 swprintf(wszMonikerName, L"Elevation:Administrator!new:%s", wszCLSID);
 wprintf(L"%s\r\n", wszCLSID);
 wprintf(L"%s\r\n", wszMonikerName);

 memset(&bo, 0, sizeof(bo));

 bo.cbStruct = sizeof(bo);
 bo.hwnd = hwnd;
 bo.dwClassContext = CLSCTX_LOCAL_SERVER;

 return CoGetObject((LPCWSTR)wszMonikerName, &bo, riid, ppv);
}

 

BOOL IsUACRequiredOperatingSystem(void)
{
 BOOL bIsUACRequired = FALSE;
 OSVERSIONINFO sInfo;
 sInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

 if (GetVersionEx(&sInfo))
 {
  if( sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
   sInfo.dwMajorVersion >= 6 &&
   sInfo.dwMinorVersion >= 0) { // Windows VISTA or Higher
   bIsUACRequired = TRUE;
  }
 }

 return bIsUACRequired;
}

 

Visual C++ 6.0 기반의 프로젝트들은 거의 대부분 ANSI나 Multibyte Character Set 기반의 문자 세트를 기준으로 프로그램이 구성되어있습니다. 확장성을 위하여 Transition이 가능한 데이터 타입 (LPTSTR, LPCTSTR, TCHAR 등)은 거의 고려하지 않았을 확률이 높습니다. 하지만 우리가 호출해야 할 API들은 유니코드 문자열을 필요로 하기 때문에 직접 유니코드를 사용하도록 기존 코드를 수정하였습니다. 그리고 더불어서, StringCchPrintf 함수를 대신하여 sprintf 계열의 함수를 직접 이용하였습니다.

 

2. 실제 ActiveX 컨트롤에 권한 상승을 적용하는 또 다른 방법

 

권용휘 MVP님의 아티클에서 설명하는 방법은, 특정 메서드나 프로퍼티의 호출 과정에서 필요로하는 권한 상승을, 권한 상승을 외부에서 요구하고 결과를 받기 위한 프록시 멤버와, 실제 처리하는 멤버로 이원화하여 구현하는 방식입니다. 대부분의 경우 이 방법으로 해결할 수 있다고 생각합니다. 하지만 간혹, ActiveX 컨트롤의 동작이나 상태, 속성을 정의하는 작업 전체가 시스템에 종속적으로 구성된 경우도 있을 수 있습니다. 이 경우에는, 격리모드에서 실행되는 ActiveX 컨트롤과는 별도로 새로운 인스턴스를 노출시켜야 할 필요가 있습니다.

 

이에 대한 솔루션은 인터넷 검색중에 발견한 어떤 블로그의 아티클에서 찾을 수 있었습니다. (http://hbesthee.tistory.com/620) 이 아티클은 델파이 기반의 솔루션을 제시하고 있었으며 저는 이것을 Visual C++ 기반의 코드로 옮겼습니다.

STDMETHODIMP CtrusEBANK::trusElevate(VARIANT *ret)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState())

 if (IsUACRequiredOperatingSystem())
 {
  ItrusEBANK *pElevatedObj = NULL;
  HRESULT hr = CoCreateInstanceAsAdmin(NULL,
   CLSID_trusEBANK, IID_ItrusEBANK,
   (void **)&pElevatedObj);

  if (SUCCEEDED(hr))
  {
   ret->vt = VT_DISPATCH;
   ret->pdispVal = pElevatedObj;
   ret->pdispVal->AddRef();
   return S_OK;
  }
  else
  {
   ret->vt = VT_NULL;
   return hr;
  }
 }
 else
 {
  ret->vt = VT_BOOL;
  ret->boolVal = VARIANT_FALSE;
 }

 return S_OK;
}

 

STDMETHODIMP CtrusEBANK::trusNeedElevate(VARIANT *ret)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState())

 ret->vt = VT_BOOL;

 if (::IsUACRequiredOperatingSystem())
  ret->boolVal = VARIANT_TRUE;
 else
  ret->boolVal = VARIANT_FALSE;

 return S_OK;
}

 

위의 코드에서는 trusNeedElevate를 이용하여 권한 상승이 지원되는 운영 체제인지 파악하는 부분과, trusElevate를 이용하여 권한 상승이 적용될 개체를 반환하는 방법 두 가지를 보여주고 있습니다. 그리고 아래의 코드는 자바스크립트에서의 실제 사용 예시입니다.

 

var obj = new ActiveXObject("EBANK.trusEBANK");

if (obj.trusNeedElevate())
{
 var result = obj.trusElevate();
 if (result) {
  obj = result;
 }
}

// 여기서부터 obj 객체 사용

 

이와 같은 방법을 통하여, 권한 상승이 온전하게 ActiveX 컨트롤에 적용될 수 있도록 하여, 원활한 동작 환경을 구현할 수 있을 것입니다.

 

3. Internet Explorer Host Window를 Elevation하는 방법 [업데이트]

 

그리고 최근에 저는 여러가지 방법을 적용해보던 중에 가장 현실적인 타협안 하나를 발견하였습니다. 바로, Internet Explorer Host Window 자체를 Runtime 도중에 Elevation 처리하는 방법으로, 기존의 응용프로그램 기반 매니페스트와 유사하게 작동합니다. 그리고 이 방법은, Host Window를 Elevation하는 데에 사용할 수 있는것 뿐만 아니라, 대리 실행해야 하는 응용프로그램의 Manifest 보유 여부에 관계없이 Elevation에도 사용될 수 있습니다.

 

참고로, 이 방법은 http://www.softblog.com/2008-02/vista-tools/ 에서 소개한 VistaTools.cxx 파일의 코드를 일부 발췌한 것임을 밝혀둡니다.

 

typedef struct _TOKEN_ELEVATION {
    DWORD TokenIsElevated;
} TOKEN_ELEVATION, *PTOKEN_ELEVATION;

 

위의 구조체는 Elevation 상태를 점검하기 위하여 필요한 구조체로 이미 Elevation 처리가 되어있는 호스트 위에서 실행되는 경우 Elevation을 다시 실행하지 않도록 하기 위하여 필요합니다. 이 구조체는 Visual C++ 6.0 기반에서 프로그램을 업데이트할 때 수동으로 지정해야 합니다.

 

#ifndef CSIDL_PROGRAM_FILES
  #define CSIDL_PROGRAM_FILES 0x0026
#endif // CSIDL_PROGRAM_FILES

 

위의 Special Folder Constant는 %PROGRAMFILES% 폴더의 경로를 가져오기 위하여 필요합니다. 마찬가지로 Visual C++ 6.0 기반에서 프로그램을 업데이트할 때 수동으로 지정해야 합니다.

 

#include <shellapi.h>
#include <shlobj.h>

 

마지막으로 위의 두 헤더 파일을 참조하도록 선언하면 일단 준비는 끝납니다.

 

BOOL IsVistaOrHigher(void)
{
 OSVERSIONINFO versionInfo;
 versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

 if (GetVersionEx(&versionInfo) &&
  versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  versionInfo.dwMajorVersion >= 6)
  return TRUE;
 else
  return FALSE;
}

 

HRESULT IsElevated(BOOL *pElevated)
{
 HRESULT hResult = E_FAIL;
 HANDLE hToken = NULL;

 if (!IsVistaOrHigher())
  return hResult;

 if (!OpenProcessToken(
  GetCurrentProcess(),
  TOKEN_QUERY,
  &hToken))
  return hResult;

 TOKEN_ELEVATION te = { 0 };
 DWORD dwReturnLength = 0;
 const int TokenElevation = 20;

 if (GetTokenInformation(
  hToken,
  (TOKEN_INFORMATION_CLASS)TokenElevation,
  &te,
  sizeof(te),
  &dwReturnLength))
 {
  hResult = te.TokenIsElevated ? S_OK : S_FALSE;

  if (pElevated)
   *pElevated = (te.TokenIsElevated != 0);
 }

 CloseHandle(hToken);
 return hResult;
}

 

BOOL ShellExecWithVerb(HWND hWnd, LPCTSTR lpVerb, LPCTSTR lpPath, LPCTSTR lpParameters, LPCTSTR lpDirectory)
{
 SHELLEXECUTEINFO executeInfo;
 memset(&executeInfo, 0, sizeof(executeInfo));

 executeInfo.cbSize = sizeof(SHELLEXECUTEINFO);
 executeInfo.fMask = 0;
 executeInfo.hwnd = hWnd;
 executeInfo.lpVerb = lpVerb;
 executeInfo.lpFile = lpPath;
 executeInfo.lpParameters = lpParameters;
 executeInfo.lpDirectory = lpDirectory;
 executeInfo.nShow = SW_NORMAL;

 return ShellExecuteEx(&executeInfo);
}

 

BOOL ShellExecWithElevation(HWND hWnd, LPCTSTR lpPath, LPCTSTR lpParameters, LPCTSTR lpDirectory)
{
 return ShellExecWithVerb(hWnd, _T("runas"), lpPath, lpParameters, lpDirectory);
}

 

BOOL OpenUrlWithElevation(HWND hWnd, LPCTSTR lpUrl)
{
 _TCHAR lpBuffer[MAX_PATH + 1];

 if (!SHGetSpecialFolderPath(hWnd, lpBuffer, CSIDL_PROGRAM_FILES, 0))
  return FALSE;

 _tcscat(lpBuffer, _T("\\Internet Explorer\\iexplore.exe"));
 return ShellExecWithElevation(hWnd, lpBuffer, lpUrl, _T(""));
}

 

위의 코드의 내용들 중에서 강조표시된 것이 실제 Elevation을 위하여 필요한 코드입니다. 그리고 실제 사용법은 아래와 같습니다.

 

STDMETHODIMP CMyAXControl::RunElevatedWeb(VARIANT *url)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState())
 USES_CONVERSION;

 CComBSTR targetUrl;
 url->vt = VT_BSTR;
 targetUrl = CComBSTR(url->bstrVal);

 _TCHAR buffer[MAX_PATH + 1];
 _tcscpy(buffer, (_TCHAR*)OLE2T(targetUrl.m_str));
 BOOL bResult = OpenUrlWithElevation(NULL, buffer);

 if (bResult)
  return S_OK;
 else
  return E_FAIL;
}

 

그리고 위의 메서드가 실제로 실행되어야 할 때와, 그렇지 않을 때를 구분하기 위하여 아래와 같이 상태 확인을 위한 메서드를 배치하는 것도 도움이 됩니다. :-)

 

STDMETHODIMP CMyAXControl::NeedElevate(VARIANT *ret)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState())

 ret->vt = VT_I4;
 ret->intVal = 0;

 if (IsVistaOrHigher())
 {
  BOOL bResult = FALSE;

  if (SUCCEEDED(IsElevated(&bResult)))
  {
   if (bResult == TRUE)
    ret->intVal = 4; // 이미 Elevation이 완료됨
   else
    ret->intVal = 3; // Elevation이 필요함
  }
  else
   ret->intVal = 2; // 상태 정보를 조회할 수 없음
 }
 else
  ret->intVal = 1; // UAC가 지원되지 않는 운영체제로 판단함

 return S_OK;
}

 

위의 메서드를 통하여, 반환값이 1 - 또는 - 4로 반환되는 경우에 한정하여 실제로 필요한 코드를 실행하고, 그렇지 않은 경우 Elevation을 수행하도록 유도하는 코드를 웹에서 작성할 수 있을 것입니다.

 

덧) 지적하거나 수정이 필요한 부분이 있으시면 댓글로 남겨주시면 바로 반영하도록 하겠습니다. 감사합니다. :-)

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

  1. 안녕하세요. 잘 읽었습니다. 혹시 질문을 좀 드려도 될까요?

    현재 만들어진 프로젝트가 VC6 MFC ActiveX (ocx)입니다. 이를 웹에서 실행시 비스타 이상에서
    UAC에 걸리잖아요.. ㅜㅜ 그래서 이를 해결해야하는데.

    2005 이상의 ATL로 변환하기가 쪼금 힘든상황입니다.( 추가된 프로젝트가 옛날 옛날 꺼라.. )

    하여 여기에 설명해주신 코드를 이용해보려고 하는데.. 그게... ATL인것 같은데... MFC AvtiveX상태에서
    권한요청 박스가 나와서 관리자를 얻어 웹에서 원하는 함수를 호출( 바탕화면 아이콘 저장)를 호출 할 수
    있을까요..

    여러가지 방법을 써봤습니다.
    1. manifest 생성+리소스추가 ( 안됨 )
    2. CoCreateInstanceAsAdmin 를 이용한 권한상승 요청 ( 안됨 = 로그를 찍어보면 권한요청 박스가 안나오지만 다 성공했따고 나오네요.. 그러나 바탕화면에 아이콘이 생성은 안되네요.. )
    3. 남정현님께서 쓰신 1번,, ( 안됨 )
    4. "" 2번 ( 웹에서 호출 할 수 있는 리턴 STDMETHODIMP 생성 불가 )
    5. "" 3번 ( "" ) - 리턴으로 ret에 관리자 권한을 줘서 웹에서 그 obj를 이용해서
    다시 ocx 내부에 있는 함수를 호출( 아이콘 생성) 하라느느 것 같은데 그 리턴 값을 넣지 못하겟습니다.

    도움 부탁 드리겠습니다.

    2010.05.24 17:31 신고 [ ADDR : EDIT/ DEL : REPLY ]
    • 여러모로 어려움이 많으신것 같네요. :-)

      우선 시도해보셨다고 했던 1번은 Inprocess Server 기반의 ActiveX 컨트롤에 대해서는 해당 사항이 없습니다. 이 방법을 적용하려면 Internet Explorer에 대해서 Manifest를 작성해야하는 우스운 상황이 연출됩니다.

      제가 작성했었던 내용들은 모두 MFC 프로젝트 위에서 테스트하고 작성했었던 내용들입니다. 혹시 구체적으로 어떤 부분에서 어려움이 있으셨었는지 말씀해주시면 좋겠습니다. :-)

      2010.05.24 18:53 신고 [ ADDR : EDIT/ DEL ]
  2. 음. 추가적으로요..
    우선 6.0 MFC ActiveX에서 코드 추가로만 자신의 ocx에서는 권한 상승후 파일 쓰기 등을 할 수 가 없는것 같은데.. 맞나요?

    대안으로 2005 Atl로 권한 상승 dll을 만들고 이 dll에서 권한 상승을 요구하는 exe 나 dll을 따로 만들어서
    호출을 하라는 것 같은데. 맞나요?

    그렇다면 권한상승용dll + 작업용(exe,dll)을 cab 만들때 같이 배포를 하라는 것인가요?
    개념이 잘 잡히지 않네요. 어짜피 파일 다운로드 설치가 권한상승dll에서는 불가능할테니 이 방법 밖에 없겠죠?

    2010.05.24 18:13 신고 [ ADDR : EDIT/ DEL : REPLY ]
    • 별도로 추가 프로그램을 작성하라는 의미는 아니었습니다. 대신, 현재 로드된 URL을 그대로 가져와서 관리자 권한을 획득한 Internet Explorer를 대리 실행할 수 있도록 해준다는 것이 제가 이 글을 통하여 설명했던 결론의 주된 골자입니다.

      2010.05.24 18:54 신고 [ ADDR : EDIT/ DEL ]
  3. 답변 감사드립니다

    우선 저의 주된 질문은 이미만들어진
    vc60 mfc activex(ocx)에 1 2 혹은 3번의 코드 추가로만으로

    이 ocx에 관리자 권한을 주는 것이 가능한건지 입니다

    ocx에서는 단순히 웹에서 아이콘파일을 다운받아 바탕화면에 바로가기 아이콘을 만드는 일늘 합니다

    리턴을로 관리자토큰을 넘겨 var obj에서 obj에 대입하여 사용이 가능한지입니다


    이것을 하기위해 위의 시도 들을 해봤는데 안되네요

    2005 atl dll로는 간단한 프로그램을 만들어 성공했습니다

    2010.05.24 22:34 신고 [ ADDR : EDIT/ DEL : REPLY ]

기술 소식2008. 8. 13. 23:58

드디어 Visual Studio 2008과 .NET Framework 3.5의 첫 서비스팩이 출시되었습니다. 여러 개발자들의 피드백에 힘입어 추가되고 개선된 부분들이 많아서 Windows Vista SP1이 나왔을 때 만큼이나 반갑습니다. 대강의 내용을 추려보면 이렇습니다.

Visual Studio 2008 Service Pack 1에서 개선되거나 달라진 점

  • WPF 디자이너의 성능 향상
  • SQL Server 2008 지원 추가 (SQL Server 2008의 모든 기능을 이용하려면 반드시 SP1을 설치해야 합니다.)
  • ADO.NET 엔티티 디자이너
  • Visual Basic과 Visual C++을 위한 컴포넌트와 도구들
  • Visual C++의 경우 이전에 커뮤니티를 통하여 소개되었고 국내에서도 몇 차례의 세미나를 통해서 언급된 Visual C++ Feature Pack이 통합되어 TR1 기술은 물론 MFC를 위한 Ribbon UI가 지원됩니다.
  • JavaScript 지원 강화, AJAX와 데이터 도구의 기능 향상, 웹 사이트 배포 기능 향상

.NET Framework 3.5 Service Pack 1에서 개선되거나 달라진 점

  • Windows Presentation Foundation 기반의 응용프로그램을 다시 컴파일하거나 변경하지 않아도 이전보다 최고 45% 이상 더 낳은 성능을 나타냅니다.
  • Windows Communication Foundation의 제어 방법이 더 정교해지고 더 다양해졌습니다.
  • .NET Framework 3.5의 설치가 이전보다 더 쉽고 자연스럽습니다. (Streamlined)
  • ADO.NET 엔티티 프레임워크, 데이터 서비스 및 SQL Server 2008과의 연동을 목표로 데이터 플랫폼 기술들이 더 좋아졌습니다.
  • 클라이언트 전용 런타임을 제공하며 런타임의 크기를 20MB 이내로 줄일 수 있습니다. (이전 .NET Framework 2.0 수준)

이 외에도 Team Foundation Server에 대한 기능이 많이 향상되었으며 좀 더 자세한 내용은 아래 기사를 참고하시기 바랍니다. 조만간 다른 언어 버전 및 Express Edition의 모든 언어 버전에 대한 SP1도 새로 공급될 예정이며, SQL Server 2008 Express Edition 및 SQL Server 2008에 대응되는 Management Studio/Express도 개발될 듯 합니다. 참고로, Visual Studio Shell 엔진도 SP1 코드 기반에 대응되는 버전이 새로 제공되므로 Shell 기반으로 독립 어플리케이션을 만드는 경우에도 새로운 SP1의 기능을 빠뜨리지 말고 가져가시면 도움이 될 것입니다. :-)

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

  1. Ribbon UI라는 것이 눈에 띄는군요 @_@;
    2008에 포함 되어 있다는게 그냥 뜬구름인줄 알았습니다 ㅎ;;

    2008.08.16 00:56 [ ADDR : EDIT/ DEL : REPLY ]
    • 원래 VC++ 2008에 없던 내용인데 Feature Pack으로 따로 소개되었었죠. 우리나라에서도 VC++ 세미나를 몇 차례하면서 소개했던 적이 있었을 겁니다. (MSDN 세미나였던걸로 기억나네요.)

      2008.08.16 15:14 [ ADDR : EDIT/ DEL ]

Visual C++2002. 8. 9. 21:20

Serialization을 구현하기 위하여 우선 가장 기초가 되어야할 사항은 새로운 클래스를 반드시 CObject 클래스로부터 상속받아야 하는 점입니다. 하지만, 이것이 다는 아니며 약간의 작업이 더 필요하다는 것은 잘 아실 것입니다.

어떤 목적의 클래스인지에 따라서 적절한 매크로 함수를 사용해야 할 것입니다. 그래서, 세 가지 종류로 구분이 되어있습니다.

  1. IMPLEMENT_DYNAMIC(), DECLARE_DYNAMIC(): CRuntimeClass를 통한 런타임 클래스 정보를 사용할 수 있도록 필요한 선언을 매크로 함수 한 줄로서 자동으로 추가할 수 있도록 만들어줍니다. DECLARE_DYNAMIC(현재 클래스 이름): 이것은 클래스의 선언부 (헤더 파일)에서 직접 써주시면 자동으로 관련된 내용을 클래스에 선언해줍니다. IMPLEMENT_DYNAMIC(현재 클래스 이름, 상위 클래스 이름): 이것은 클래스의 소스 코드 부분 (CPP 파일)의 상단부에 기재하여 주시면 됩니다.
  2. IMPLEMENT_DYNCREATE(), DECLARE_DYNCREATE() : 런타임 정보와 동적 개체 생성, Assert/Valid 등을 지원합니다. 사용 방법은 역시 동일합니다.
  3. IMPLEMENT_SERIAL(), DECLARE_SERIAL(): CObject 클래스에서 사용할 수 있는 모든것을 가능하도록 지원합니다. 동적 개체 생성, 직렬화 등등이 있겠군요. 사용 방법은 역시 동일합니다.  
Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 8. 1. 19:02

Windows 기반에서 웹 그래픽을 처리하기 위해서는 이전까지는 JPEG나 GIF 이미지의 Static Library 또는 관련 DLL들을 얻어서 써야 하는 매우 번거로운 작업을 해야만 했습니다. 하지만, MFC 7.0에서는 이러한 수고스러움을 덜어주기 위하여 새로운 클래스를 도입하게 되었는데, 바로 CImage 클래스입니다.

CImage 클래스는 CBitmap 클래스의 확장 개념입니다. 기존의 비트맵 이미지 객체로도 손쉽게 불러올 수 있음은 물론이고 기본적인 수준의 GIF, JPEG, PNG, BMP 이미지를 사용할 수 있으므로 공들여서 웹 그래픽 작업을 번거롭게 하는 일은 없어졌습니다.

여러분은 이미지를 불러들이기 위하여 두 가지 함수를 사용하실 수 있습니다. Load()와 LoadFromResource()라는 함수입니다. Load() 함수는 파일 경로명을 지정하거나 IStream 인터페이스의 포인터 객체를 얻는 방법이 있습니다. 대개의 경우는 파일 경로명을 사용하겠지요. LoadFromResource()는 리소스의 이름 데이터나 리소스 ID를 지정할 수 있습니다.

이렇게 불러들인 이미지는 기존의 CBitmap 클래스처럼 사용하시면 됩니다. 이미지를 출력하기 원하는 DC에 뿌려주기만 하면 됩니다. 비트맵 핸들을 얻어야할 필요가 있다면 연산자 오버로딩이 되어져 있기 때문에 그냥 HBITMAP에 대입해서 쓰면 됩니다.

또한, 알파 블렌딩과 같은 고급 그래픽 효과도 사용할 수 있으니 참고하시기 바랍니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 7. 24. 13:41

Visual C++ .NET, 즉 MFC 7.0에서는 이전 버전인 MFC 6.2보다 편리하게 변경된 사항이 몇 가지가 더 있습니다. 그 중에 하나가 CObject 클래스에서의 직접 상속입니다. 물론 이전에도 아래와 같은 절차를 통하여 상속받는 것을 지원하였지만 .NET 버전에 들어와서부터는 좀 더 처리가 간결해졌다는 뜻입니다.

MFC 클래스를 작성할 때에 클래스 작성 마법사는 상속 가능한 클래스 리스트를 보여줍니다. 이 때에 CObject를 포함한 다수의 새로운 클래스를 제공합니다.

여러분은 여기서 CObject로 상속을 받아서 몇 가지의 작업을 더해주면 CObject와 동일한 기능을 수행하는 또 하나의 여러분만의 새로운 데이터 클래스를 생성할 수 있습니다.

이전에도 작성했었던 방법이지만 MFC 7.0에서도 그대로 사용할 수 있습니다. 아니, 약간 더 구체적으로 정보를 더 알려드리도록 하겠습니다. 클래스의 사용 용도에 따라서 여러분은 선언의 수준을 달리할 수 있습니다.

* DECLARE_DYNAMIC(class_name) 및 IMPLEMENT_DYNAMIC(class_name, base_class_name) : CRuntimeClass* 구조체로 조사가 가능한 일반적인 형태의 런타임 클래스로 만드는데에 필요한 약간의 데이터를 더 포함합니다. #DEFINE 선언이기 때문에, 프리프로세서가 컴파일 직전에 실제 코드로 변환하여 처리하도록 되어있습니다.

DECLARE_DYNAMIC() 선언은 클래스의 선언부에 직접 사용하시면 됩니다. 단 주의하실 점은 DECLARE_DYNAMIC() 선언 그 자체가 액세스 권한 적용 대상이 아니라는 점입니다. 즉, 아래와 같은 선언을 할 경우 컴파일 에러가 발생할 수 있습니다.

    class CExample : public CObject

    {

    public:

      DECLARE_DYNAMIC(CExample)

      CExample();

      virtual ~CExample();

    };

위와 같은 코딩을 올바르게 고치는 방법은, DECLARE_DYNAMIC() 선언을 public: 영역 밖에서 코딩해주는 것입니다.

그리고, DECLARE_DYNAMIC() 선언으로 끝나면 안되며, DECLARE_DYNAMIC()과 연관되는 멤버 함수의 선언을 위하여 IMPLEMENT_DYNAMIC()을 소스 코드 파일 (.cpp)의 프리프로세서 선언문 바로 아래에 넣으셔야 합니다.

* DECLARE_DYNCREATE(class_name) 및 IMPLEMENT_DYNCREATE(class_name, base_class_name) : 이 매크로는 앞서 거론한 DECLARE_DYNAMIC()과 IMPLEMENT_DYNAMIC()의 내용을 포함함과 동시에, CDocTemplate와 같은 클래스에서의 동적 생성 프로세스를 지원하도록 해줍니다.

기본적인 사용 방법은 위와 같습니다. 하지만, 위의 선언을 이미 하였을 경우 그 선언 대신 사용해야 합니다. 그렇지 않으면 컴파일 시 중복 선언 에러를 발생하게 됩니다. 또한 최소한 1개 이상의 기본 생성자가 필요합니다.

* DECLARE_SERIAL(class_name) 및 IMPLEMENT_SERIAL(class_name, base_class_name, wSchema) : 이 매크로는 앞서 거론한 DECLARE_DYNCREATE() 및 IMPLEMENT_DYNCREATE()의 내용을 포함함과 동시에, 직렬화 프로세싱을 지원하도록 해줍니다. 이 선언이 이루어져야 올바르게 Serialize(CArchive& ar) 함수를 재정의할 수 있습니다. wSchema에는 여러분이 임의의 버전을 입력하도록 되어있습니다. 대개 0에서부터 시작하며 프로그램의 메이저 버전을 올릴 때에 같이 올리곤 합니다.

역시 사용법은 같습니다. 중복 선언에 유의할 것과, 최소 1개 이상의 기본 생성자가 요구됨을 주의하면 됩니다.

다음 Chapter에서는 이렇게 선언한 매크로를 어떻게 사용할 수 있는지를 알아보겠습니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 7. 19. 19:11

여러분은 Managed Extensions for C++ 프로젝트로 콘솔 프로그램을 작성하기 시작하였을 때 전에는 볼 수 없었던 새로운 키워드와 새로운 객체를 보실 수 있습니다.

우선 오늘은 새로운 키워드에 대해서 알아보도록 할 까 합니다.

1. #using 전처리기 구문

#using은 .NET 프레임 워크의 컴파일러만이 유일하게 감지해내는 전처리기 구문입니다. 이것은 #include와 유사한 성격을 띄지만 좀 더 유연하고 포괄적인 내용입니다.

#using은 *.h 파일과 같은 순수 소스 코드를 불러들이기 위한 것이 아니라 미리 컴파일된 닷넷 프레임워크 DLL을 직접 불러다 쓰거나, 아니면 기존에 누군가가, 혹은 자신이 생성했었던 프레임워크 호환 DLL을 불러다 쓸 때에 사용하는 구문입니다.

이 DLL은 닷넷 개발 툴에서만 사용이 가능하며, 다른 델파이와 같은 개발툴에서는 호환되지 않는 형식의 이진수 체계를 사용합니다. /clr 컴파일러 옵션을 더하고 나서 여러분은 코드의 맨 위나 stdafx.h에 이와 같은 선언을 더해줄 수 있습니다.

#using <mscorlib.dll>

이는 가장 핵심적인 닷넷의 기능을 축약해 담은 내용이 컴파일된 DLL을 로드하겠다는 의미입니다. 실제로 mscorlib.dll 파일은 존재하는 파일입니다.

2. 네임스페이스 객체와 namespace 키워드

네임스페이스라는 객체는 닷넷의 유일무이한 트레이드마크입니다. 네임스페이스 그 자체는 별 의미가 없으며 단지 클래스나 또 다른 네임 스페이스를 포함하기 위한 기능을 가질 뿐입니다.

이 네임스페이스는 파일 시스템의 디렉터리 구조와도 같아서, 클래스 이름이 동일하더라도 네임스페이스의 위치가 다르면 완전히 다른 클래스로 분리가 됩니다. 이에 따라서 클래스에서도 전역 클래스와 로컬 클래스로 다시 구분되어졌습니다.

이 네임스페이스 객체를 생성하기 위해서 여러분은 단지 namespcae 이름 {으로 선언을 시작해서 }; 로 선언을 끝내기만 하면 됩니다.

3. 네임스페이스 객체에 접근하는 방법은?

네임스페이스를 별도로 객체로 선언하여 접근한다는 생각을 하셨다면 착각하셨습니다. 올바르게 액세스하기 위해서 반드시 :: (스코프 연산자)를 사용해야 합니다. 별도의 선언 없이는 네임스페이스 내부의 클래스도 :: (스코프 연산자)로 접근해야 합니다.

4. __gc 키워드

__gc가 의미하는 것은 Garbage Collected를 뜻합니다. 하지만 길게 생각할 필요는 없으며 __gc로 선언되는 것들은 모두 닷넷 프레임워크 수중안에서 관리가 이루어지므로 사용자가 수동으로 delete 키워드를 사용해서 제거할 필요는 없습니다. 이 키워드를 사용할 수 있는 대상의 제한은 없습니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 7. 18. 21:15

[시작하기 전에]

본 코너는 타 코너보다 늦게 시작하였지만 꾸준히 관심을 가져주시고 읽어주셔서 어느덧 40회 이상의 글 게재 횟수를 기록하게 되었습니다. 본 코너는 방학 중에도 꾸준히 업데이트가 될 것이며, 앞으로도 이곳에서 유용하고 깊이있는 Windows 프로그래밍 정보를 게재하기 위하여 2차 개정안을 시행합니다. 다른 개정 사항은 없으며 아래 사항 한 가지가 있습니다.

* Chapter #46 이후에 기준이 될 주 개발 도구는 Microsoft Visual C++ .NET입니다. 따라서, 기존의 MFC 라이브러리 4.2에 없었던 새로운 클래스나 새로운 기능들이 언급이 될 수도 있습니다.

Visual Studio .NET으로 프로그램을 작성하다보면 전에 보지 못했었던 C++의 새로운 프로젝트 옵션 하나가 보일 것입니다. 바로, Managed Extension for Visual C++이라는 것입니다.

이 Managed Extensions의 특징은 "관리된다"라는 점에 있습니다. 구체적으로 말하자면 다른 언어와의 호환성을 위하여 설계된 CLI (Common Language Infrastructure) 규격에 의거하여 프로그램을 최적화한다는 점입니다. 이렇게 최적화시킨 프로그램은 .NET Framework에서의 사용이 훨씬 간편하고 유연합니다.

기존의 수많은 어플리케이션들이 .NET Framework라는 견인차에 의해서 재사용이 가능한지는 .NET Framework가 발매되기 시작하면서부터 시비거리가 되어왔던 사안입니다. 하지만, Visual Studio .NET에서 그 시비의 종결점을 찾았습니다. 바로 Managed Extensions인 것입니다.

실제로, 관리되는 코드를 사용해야 하는 이유 네 가지를 들 수 있습니다.

첫 번째, 관리되지 않는 기존의 프로그램을 관리 가능한 상태로 변경하여 닷넷 프레임워크 및 인프라와 잘 궁합이 맞는 프로그램으로의 마이그레이션을 하기 위함입니다. 물론, 기존의 기능들을 거의 변경할 필요 없이 언제든지 닷넷 프레임워크만의 기능들을 가져다 쓸 수 있습니다.

두 번째, 다른 .NET 호환 언어로 여러분의 프로젝트 내에있는 클래스나 멤버 함수들을 사용할 수 있습니다. 쉬운 예로 미리 작성해 두었던 기존의 클래스를 Visual Basic .NET이 경유 참조하여 값을 가져다 쓴다거나, Visual C# .NET이 경유 참조하여 값을 가져다 쓴다거나, 혹은 ASP.NET, GTK# (MONO 프로젝트의 독자적인 언어)과 같은 언어등에서도 얼마든지 가져다 쓸 수 있습니다.

세 번째, 이와는 반대로 여러분의 프로젝트가 다른 언어로 작성된 프로젝트의 것을 그대로 참조할 수도 있습니다.

네 번째, 관리됨의 여부에 따라서 완벽히 분리된 두 개의 코드를 하나의 EXE 파일안에 담을 수 있습니다. 다시 말해서, 관리가 되는 코드로 작성을 하였든 그렇지 않았든 그 여부와는 관계없이 프로그램이 알아서 영역을 설정하고 자동으로 변수들을 참조할 수 있도록 해준다는 것입니다.

이 Managed Extensions는 Visual Studio 내의 모든 언어가 다 사용할 수 있습니다. Visual C++ .NET, Visual Basic .NET, Visual C# .NET, Visual J#.NET 등등이 있겠지요.

Managed Extensions를 사용하여 언어를 한데 묶을 수 있습니다. 이는 곧 다른 언어로의 포팅 작업 없이도 닷넷 프레임 워크안에서 프로그램 끼리의 데이터 공유가 매우 편리하고 용이하다는 것을 반증하기도 합니다.

실제로 Managed Extension을 추가하는 방법은 프로젝트 설정에서 할 수 있습니다. 프로젝트 설정에서 Managed Extension을 사용하겠다고 여부를 설정하면 컴파일러는 이 여부를 확인하고 자동으로 컴파일할 때에 Managed Extension에 필요한 참조와 라이브러리, DLL을 추가하여 컴파일을 시작할 것입니다.

자세한 정보는 Visual Studio .NET 설명서를 통하여 보실 수 있습니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 7. 1. 17:55

이전 Chapter에서 언급했었던 Break Point를 응용할 수 있는 툴입니다.

Quick Watch의 용도는 어떤 변수의 값이 특정 코드에 의하여 올바르게 입력이 되었는지 조회하여 볼 수 있는 도구입니다. 이 도구를 사용하여 여러분이 작성한 코드가 올바르게 동작하였는지 확인해 볼 수 있습니다.

Quick Watch는 디버그 도구 모음중에서 찾아볼 수 있습니다. 별도의 대화 상자가 나타나는데, Expression에서 원하는 변수명이나 변수가 클래스인 경우 빠르게 접근해갈 수 있는 수식을 입력할 수도 있습니다. 변수의 입력 조건은 제한이 없습니다. 즉, 지역/전역의 구분이 없이 직접 존재하는 변수명만 입력하면 됩니다.

그리고 지속적으로 조사할 변수일 경우, 하단의 Watch 프레임으로 항목을 드래그해서 등록시킬 수 있습니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 7. 1. 17:44

여러분이 프로그램을 작성할 때에 여러분이 작성하기는 했지만 제대로 수행이 되는지가 의심스러운 부분이 생기는 곳이 있습니다. 혹은, 남이 작성한 클래스나 함수가 올바르게 동작이 되는지 테스트 해보아야 할 때가 있습니다. 이럴 때 여러분은 어떻게 하시겠습니까?

이 Chapter에서 Break Point에 대해서 알고 난 다음 부터는 달리 고민하실 필요 없습니다. 의심스러운 줄에 단지 F9키를 눌러서 Break Point를 걸면 됩니다.

이렇게 Break Point가 걸린 부분을 디버그 모드로 컴파일하고 나서 어떤 기능을 수행하도록 프로그램에게 요청하면 프로그램은 자동으로 Halt 상태로 전환이 되어 Visual Studio의 디버거에 의해서 컨트롤될 수 있도록 바뀝니다.

이 상태에서 여러분은 이전 Chapter인 Call Stack, 다음 Chapter에서 언급하게 될 Quick Watch나 Watch View등 강력한 도구를 자유자재로 사용하실 수 있습니다.

ps (2006年 12月 16日) - Visual C++의 Break Point 작동 원리에 대한 블로그 글도 같이 보시면 좋아요 :-)

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 7. 1. 17:35

MFC용 어플리케이션을 작성하다보면, 이따금씩 Debug Assertion Failed라는 대화 상자와 쉽게 마주치곤 합니다. 이런 대화 상자들이 생기는 원인은 간단한 경우일 수도 있지만 매우 복잡한 경우가 될 수도 있습니다.

문제가 있는 코드를 일일이 눈으로 훑어보면서 찾아내는 작업도 디버깅입니다. 하지만, 이것은 프로그램의 규모가 커지면 커질 수록 부적절한 방법이 됩니다. 이런 부적절하고 비 효율적인 디버깅은 별 쓸모가 없습니다.

프로그램의 어떤 기능이 수행되기 위해서 수행되어진 내역들을 차근차근히 모아놓고 있는 스택 스토리지가 디버그하는 도중에 자동 생성되어 알아서 동작하게 됩니다. 이 스택의 이름은 호출 스택 (Call Stack)이라고 합니다.

이 호출 스택 내역을 조회해보면 어떤 부분에서 문제가 발생하게 되었는지 단번에 파악할 수가 있습니다.

호출 스택에 내역을 저장하고 조회하기 위해서는 디버그 모드로 프로젝트를 컴파일해야 합니다. MFC 완벽 가이드를 구매하면서 받으셨던 부록 CD의 디버깅 편에 대한 예제가 담긴 프로젝트를 열고 컴파일하십시오.

특정 부분에서 "Debug Assertion Failed"라는 대화 상자가 나타날 것입니다. 여기서, "Retry"을 선택하여 디버그를 시작하십시오. 어떤 부분에서 문제가 생겼음을 정확히 알려줄 것입니다. 하지만, 여러분은 이곳에서 무엇을 잘못 작성한 것인지 알 길이 없습니다. 즉, 별로 도움이 되지 않는 정보라는 점이죠. 하지만, 포기하지 마시고, 디버그 도구 모음에 표시된 아이콘 들 중에서 "Call Stack" 항목을 선택하십시오. (아이콘 위에 잠시 포인터를 대면 툴팁 설명이 나타나는데 이 설명의 이름이 "Call Stack"인 항목을 선택하십시오.) 그러면 자그마한 팝업창과 함께 리스트가 나타납니다. 아래로 갈 수록 먼저 수행되어진 기능들이며, 맨 위의 부분이 문제가 생긴 부분입니다.

여러분이 수행한 기능은 대개 2~3단계 뒷쪽에 기록되어져 있습니다. 여러분이 작성한 클래스의 이름이 등록된 항목을 더블 클릭하십시오. 무엇이 문제인지 확인하실 수 있습니다. 이제, 디버그 도구 모음에서 디버그 중단 아이콘을 클릭하여 다시 개발자 환경으로 돌아오신 다음 문제가 생긴 코드를 고쳐서 다시 빌드하십시오.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 6. 25. 21:37

Windows 기반의 어플리케이션들은 일반적으로 Win32 커널이 띄워져있는 상태에서 수행되도록 설계가 되어있습니다. 만일, 순수한 16비트 상태의 Native MS-DOS나 MS-DOS와 호환이 가능한 FreeDOS나 DR-DOS, 혹은 OS/2 콘솔 등에서 Windows 기반의 어플리케이션을 수행하려고 하였을 때에 여러분은 다음과 같은 에러 메시지를 접할 수 있습니다.

This program cannot be run in DOS mode.

이러한 에러 메시지를 접할 수 있는 이유는 매우 당연한 사실입니다. 하지만, 이 에러 메시지를 그냥 무시하고 지나치지 맙시다.

Windows 95 이상의 배포 패키지의 설치 부트 스트랩 파일들을 살펴봅시다. Windows 95, 98, Me에서 수행되는 것은 물론이거니와 Windows 3.1, MS-DOS에서도 수행이 됩니다. 이것이 가능한 이유가 무엇일까요? MS사만의 편법? 아니면 MS사만의 기술적 노하우? 아닙니다.

의외로 간단한 비밀이 있습니다. 바로 서브 시스템이라고 하는 부분인데, 서브 시스템은 현재 컴퓨터 시스템에 수행중인 운영 체제나 환경에 따라서 프로그램을 구동시켜주는 부분입니다.

일반적으로 Windows 어플리케이션들은 32비트 기반의 Windows 환경이나 16비트 환경이지만 32비트 DLL을 사용할 수 있는 환경이 갖추어진 상태 (Windows 3.1 시스템에 Win32s 패키지를 설치한 경우...)에서 수행되도록 설계되어있습니다.

하지만 특정 프로그램에 의하여 서브 시스템을 조작한 상태에서 어떤 어플리케이션을 수행하게 되면 그 어플리케이션에 별도의 기능이 포함되어져 있을 경우 그 기능으로 수행이 됩니다. 좀 더 쉬운 말로 하자면, Windows 프로그램이 서브 시스템 조작 트랩에 의하여 MS-DOS창에서 수행되는 프로그램으로 전환되는 것이 가능하다는 점입니다.

이에 관련된 예제를 게시해놓았습니다. 잘 검토하여 보시고 분석해 보시기 바랍니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 6. 25. 21:31

일반적으로 콘솔 어플리케이션상에서는 MFC 컴포넌트 및 클래스를 사용할 수 없는 것으로 알고 있었습니다. 하지만, 콘솔에서도 MFC를 얼마든지 사용할 수가 있습니다.

콘솔에서 MFC를 사용할 수 있도록 해주는 방법은 두 가지가 있습니다.

  • 처음부터 MFC 타입 콘솔 프로젝트로 시작한다.
  • 보통의 콘솔 프로젝트에서 MFC 라이브러리를 사용하도록 지정함과 동시에 #include로 필요한 MFC 헤더 파일들을 추가한다.

이 Chapter에서는 2번 방법을 중점으로 하고 시작하도록 하겠습니다.

우선, 예전처럼 우리는 콘솔 프로젝트를 새로 하나 만들어보겠습니다. 그냥 만들던대로 만드십시오. 그러면, 새로운 웍스페이스가 하나 나타나고 좌측의 프로젝트 윈도우에는 Globals 폴더가 나타날 것입니다.

프로젝트가 생성되면, Alt + F7키를 눌러 프로젝트 셋팅 대화 상자를 띄우세요. 그러면, Microsoft Foundation Classes에 대해서 묻고 있는 리스트 박스가 맨 첫 번째 항목으로 보입니다. 여기서, 여러분은 나타나는 세 가지 항목중에 "Use MFC in a shared DLL"을 선택하고 "OK"을 눌러서 이 대화 상자를 종료하시면 됩니다.

이제 여기에 단지 MFC 관련 헤더 파일들을 끼워넣어주는 일만이 남게 되었습니다. 아래는 MFC 관련 내용을 수록하고 있는 헤더 파일들입니다. 원하는 헤더 파일을 알맞게 삽입하시는 것이 컴파일된 바이너리 파일의 용량을 줄여주는 길입니다.

    #include <afx.h> // 가장 기초적인 MFC 요소들.

    #include <afxwin.h> // 윈도우 클래스들.

    #include <afxext.h> // 확장 클래스들.

    #include <afxdtctl.h> // 윈도우 컨트롤 클래스들.

    #include <afxcmn.h> // 윈도우 공용 컨트롤 클래스들.

    #include <afxinet.h> // 인터넷 기능 클래스들.  

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 6. 20. 16:56

Visual C++ 6.0에서는 기본적으로 디버그 모드로 프로젝트를 빌드하게금 설계가 되어있습니다. 하지만, 이러한 디버그 모드는 정말 완벽하게 제 기능을 다 하고 있지는 않습니다. 당장은 체감할 수 없을것이지만 좀 더 큰 프로그램이나 좀 더 깊숙한 어플리케이션을 작성하다보면 디버그 모드가 완벽하지 않다라는 것을 쉽게 접할 수가 있게 됩니다.

무엇이 문제이길래 디버그가 완벽하게 동작하지 않는 다는 것일까요? 바로 디버그 심볼의 유무 때문입니다. 디버그 심볼은 디버그를 하는데에 있어서 정확히 디버그를 할 수 있도록 도와주는 유용한 수단입니다. 특히 이 디버그 심볼들은 Windows NT 환경 (Windows NT 4.0 SP6, Windows 2000 SP2, Windows XP SP1, Windows .NET Servers 등등...)에서 어플리케이션을 작성할 때에는 절대적인 위력을 발휘합니다.

실제로 여러분이 프로그램을 디버그 모드로 빌드하고 디버그 상태로 프로그램을 수행하고 난 다음 종료시켜서 Output에 출력된 메시지들을 읽어보시면 다음과 같은 에러 메시지를 찾아볼 수 있습니다.

    Loaded symbols for 'C:\WINDOWS\SYSTEM\MFCO42D.DLL'

    Loaded 'C:\WINDOWS\SYSTEM\USER32.DLL', no matching symbolic information found.

    Loaded 'C:\WINDOWS\SYSTEM\ADVAPI32.DLL', no matching symbolic information found.

    Loaded 'C:\WINDOWS\SYSTEM\GDI32.DLL', no matching symbolic information found.

    Loaded 'C:\WINDOWS\SYSTEM\KERNEL32.DLL', no matching symbolic information found.

    <이하 생략>

여기서 no matching symbolic information found. 라고 출력된 해당 DLL 파일은 디버그 심볼이 설치되지 않았기 때문입니다.

그렇다면 이러한 디버그 심볼들을 어디에서 설치할 수 있을까요? 여러분이 Visual Studio 6.x 제품의 CD-ROM들 중에서 찾아보실 수 있는 CD 중 Visual Studio 6.0 둘 째 CD가 있습니다. 이 CD안에는 이러한 디버그 심볼들을 포함하여 Visual Studio 6.0을 완전하게 만들어주는 MS사의 툴킷이나 서드 파티 회사들의 유용한 유틸리티들이 포함되어져 있습니다.

그리고 당장 디버그 심볼을 설치할 수 있는 방법은, Visual Studio 6.0 프로그램 그룹에서 Microsoft Visual Studio 6.0 Tools의 Windows NT Debug Symbol Setup이라는 아이콘을 클릭함으로서 설치할 수 있습니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 6. 20. 16:45

예전의 DOS 프로그램에서는 다음과 같은 함수들을 사용하여 MS-DOS나 Windows의 셸 커맨드를 처리하곤 하였습니다.

int main(int argc, char** argv);

하지만, Windows용 MFC 어플리케이션에서는 일단 기본적으로는 이러한 내용들을 쉽게 처리해주는 기능을 제한적으로만 CCommandLine이라는 클래스를 통하여 처리를 합니다. 하지만 이 클래스로 처리할 수 있는 파라메터는 MFC 어플리케이션과 직접 연결된 기능들, 그러니까 인쇄 기능이나 미리보기 기능, 파일 오픈 등의 기능외에는 다른 것들은 수용하질 못합니다. 그러면, 사용자 정의한 스위치들은 어떻게 처리하는 게 좋을까요?

Windows 전역 변수 중에 (::라는 스코프 연산자를 입력해보십시오.) __argc와 __argv라는 것 두 개가 있습니다. 네, 바로 파라메터죠.

이 파라메터들은 어플리케이션이 처음 수행될 때에 셸로부터 입력받아진 명령들을 고스란히 담아서 저장했다가 어플리케이션이 끝날때까지 보존하고 있습니다. 다시 말하자면, 이 데이터들은 언제 어느때건 사용할 수가 있다는 것입니다.

여러분은 이 데이터들을 CString이나 LPCTSTR과 같은 문자열 버퍼에 복사본을 만든뒤에 그대로 사용하실 수 있습니다. 다음이 그런 예제가 될 수 있을 것입니다.

    CString strParam = __argv[1];

    if(strParam == "/install") AfxMessageBox("/install 발견.");

    if(strParam == "/uninstall") AfxMessageBox("/uninstall 발견.");

    if(strParam == "/run") AfxMessageBox("/run 발견.");

    if(strParam == "/pause") AfxMessageBox("/pause 발견.");

    if(strParam == "/resume") AfxMessageBox("/resume 발견.");

    if(strParam == "/stop") AfxMessageBox("/stop 발견.");

* 참고 : 파라메터임을 나타내기 위하여 일반적으로 '/', '-' 또는 '--'와 같은 구분 기호를 사용해줍니다. 이것은 파일 경로 지정과의 혼동을 막기 위한 하나의 약속같은 것이지요.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 6. 16. 17:47

프로젝트의 규모가 커지고 복합적인 규모로 발전될 수록 각종 리소스나 클래스 파일들의 크기도 점점 방대해지게 됩니다. 하지만, 이러한 것들을 보기좋고 일관성있게 카테고리별로 배치하고 싶다면 어떻게 하는 것이 좋을까요? 바로 "폴더"입니다.

프로젝트 내에서의 폴더 개념은 프로젝트 파일 내에서만 인식할 수 있는 카테고리 구분자입니다. 실존하는 디렉터리 타입의 폴더와는 개념이 다르죠.

프로젝트 윈도우 (좌측의..)에서 새로운 폴더를 만들기 위해서는 오른쪽 버튼으로 폴더를 만들 위치의 바로 윗 항목을 클릭한 다음 "New Folder"를 눌러서 생성할 수 있습니다. 그 다음, 만든 폴더에다가 원하는 클래스를 드래그해서 원하는 폴더까지 끈 후 드롭하면 보기좋게 배치가 됩니다.

프로젝트 윈도우에서는 최상위 항목을 제외한 기타 모든 항목들에 대해서 종속적인 위치를 가지는 폴더를 생성할 수가 있습니다. 즉, 리소스 뷰, 파일 뷰, 클래스 뷰에서 폴더를 쉽게 생성할 수가 있다는 것입니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 6. 16. 01:00

중요하게 읽고 알아두셔야 할 Chapter라고 생각이 됩니다.

매번 어떤 새로운 데이터 클래스를 작성할 때마다 항상 CObject로부터 상속을 받아서 데이터 클래스를 작성해왔습니다. 하지만, 왜 꼭 이렇게 해줘야하는것인가요?

MFC의 구조성을 활용한 아주 좋은 프로그래밍 방법중에 하나라는 사실을 이 Chapter를 통하여 알아가시기 바랍니다.

실제로 MFC로 작성된 프로그램은 표준적인 파일 입/출력을 개별적으로 처리하지 않습니다. 모두 직렬화 (Serialization)이라는 함수 안에 몰아서 처리하는 경우가 대부분입니다. 왜일까요?

프로그램에서 "파일"의 "저장"을 선택해서 저장이 될 수 있는 경우는 직렬화 함수를 제외하고는 없습니다. 다시 말해서, 개별적으로 파일 입출력을 구현하려면 별도의 메뉴를 또 만들어야 한다거나, 수작업으로 특정 위치에서 불러들이게금 해줘야합니다. 즉, 훨씬 불편하다는 이야기죠.

그렇다면 이런 불편함을 겪지 않기 위해서는 직렬화 함수를 사용해야 할텐데, 어떻게 사용할까요? 네. 바로, CObject로부터 상속받아오는 것입니다.

CObject로부터 여러분이 새로운 데이터 클래스를 상속받아오면 몇 가지 정의만으로 충분히 파일의 저장과 열기가 자동으로 이루어지도록 구성할 수 있습니다.

파일 처리의 용이성 다음으로 중요한 이유는 다양한 클래스와의 호환성입니다. CObject는 거의 모든 MFC 클래스의 가장 높은 선조격인 클래스입니다. 이런 선조 클래스를 기반으로 작성된 수많은 클래스들과 당연히도 호환이 됨은 물론 아주 좋은 성능을 보여주게 되어있습니다. 그런 예로, CObList가 있겠지요.

CObject로 클래스를 상속받아서 새 데이터 클래스를 만드는 결정적인 이유는 다름이 아니라 손쉽고 빠른 파일 처리를 위해서라는 점입니다. 그외에, 실제로 CObject로부터 얻게 되는 이점을 따지자면 상당히 많습니다. 나중에 다시 설명하도록 하지요.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 6. 16. 00:49

클래스 위저드나 기타의 MFC용 내부 유틸리티로 CString 변수를 선언하고 나면 항상 초기화 선언에 _T("")라는 명령어가 포함되어있는것을 보아왔습니다. 하지만, 정확히 이것이 무엇인지 개념이 아리송해서 모르고 지나가기가 쉽습니다만, 확실히 정리하죠.

일단 _T("")와 같이 세미콜론이 없는 상태에서 종결되는 구문들이 MFC에서는 다수 존재합니다. 이러한 구문들은 모두 매크로 구문이라고 부르고 있는 것들이며, 몇 줄의 코드나 복잡한 함수식을 간단한 매크로 구문 하나로 압축해놓은 것이 일반적입니다.

이런 매크로 함수들이 리턴해주는 값들은 클래스보다도 주로 Win32 환경에서 쓰이는 데이터타입들을 리턴해주게 됩니다. 예를 들면, 핸들 값이나 LPCTSTR, LPVOID 값들이 그런 것들이죠.

그렇다면, _T("")의 실제 리턴값은 무엇일까요? 바로, 아무것도 들어있지 않은 NULL 상태의 LPCTSTR 변수값입니다. 즉, 초기화를 의미하는 내용이죠.

그러면 CString에서 이 값을 어떤 과정을 통해서 받아들이게 되는지는 자동으로 계산이 나오게 됩니다. 네, 그렇습니다. 바로 연산자 오버로딩에 의해서 처리되죠. CString 선언을 찾아보면 = (Equal) 연산자 오버로딩이 LPCTSTR 또는 CString을 처리하도록 서술되어있습니다.

결국은 아무 값도 없는 LPCTSTR을 CString에 던져준다는 것이 됩니다.

이 Chapter에서 알아두셔야 할 점은 초기화 방법이 때로는 매크로 함수에 의해서 이루어지기도 할 수 있음입니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 6. 13. 18:50

실제로 Microsoft Windows 운영 체제를 구성하고 있는 컴포넌트 프로그램들의 정보 대화 상자를 살펴보면 공통적인 모습을 갖추고 프로그램의 이름과 제작자 정보들을 보여줍니다. 이러한 대화 상자는 어떻게 실행이 되어지게 되는 걸까요?

이 대화 상자 역시도, 글꼴 지정 대화 상자나 파일 작업 대화 상자와 같이 공용 대화 상자의 일종입니다. Windows 운영 체제의 버전은 물론 프로그램의 버전을 같이 표시해 줍니다. 하지만 한 가지 주의해야 할 점은, 이 대화 상자를 사용하여 표시되는 정보는 Microsoft가 소유권을 가지고 있는 것으로 표시가 됨에 유의해야 합니다.

스코프 연산자 (::)로 전역 API 함수들을 리스팅해보면 다음과 같은 꼴의 함수를 찾아보실 수 있습니다.

int ShellAbout(HWND hWnd, LPCTSTR szApp, LPCTSTR szOtherStuff, HICON hIcon);

각 파라메터들에 대해서 설명하겠습니다.

  • HWND hWnd : 모달 윈도우가 띄워질 부모 윈도우의 핸들을 받습니다.
  • LPCTSTR szApp : 제품의 이름이나 프로그램의 제목을 사용합니다.
  • LPCTSTR szOtherStuff : 부가 정보 및 덧말을 넣을 때 사용합니다.
  • HICON hIcon : 프로그램을 상징하는 아이콘의 핸들을 받습니다.

리턴값의 구분에 대해서 설명하겠습니다.

  • 만약 올바르게 창이 띄워지면 TRUE (Win32)를 리턴합니다.
  • 그렇지 않다면 FALSE (Win32)를 리턴합니다.

각 파라메터를 지정할 때에는 아래와 같이 지정하는 것이 일반적입니다. 참고로, 이 Chapter에서 사용될 프로젝트명이 CommonAbout이라고 가정하고 설명을 드리겠습니다.

* HWND hWnd

표준 MFC 프로젝트로 프로그램을 작성하였을 때에는 분명히 어플리케이션 클래스가 존재합니다. 여기서는 CCommonAboutApp 클래스이겠군요. 이 클래스의 멤버 변수 중에는 m_pMainWnd라는 변수가 있습니다. 이것은 어플리케이션을 연결하는 메인 프레임 윈도우에 대한 접근 변수입니다. 즉, 본 프로젝트에서의 CMainFrame 클래스에 연결시킨 것이죠. 또한 CMainFrame 클래스는 본 어플리케이션에서 가장 최상위 부모창에 해당하게 됩니다.

이 함수의 첫 번째 파라메터는 이 CMainFrame과 연결된 부모창의 핸들값을 요구하고 있습니다. 그렇다면 어떻게 이 핸들을 얻어낼 수 있을까요? CMainFrame 클래스의 멤버 함수 중에 GetSafeHwnd()라는 함수가 있습니다. 여러분은 이 함수의 리턴값을 첫 번째 파라메터에다가 직접 기입하시면 됩니다.

* LPCTSTR szApp, LPCTSTR szOtherStuff

원하는 대로 입력하시면 됩니다. 이 두개의 파라메터 모두 _T("") 와 같이 공백을 줄 수 있습니다.

* HICON hIcon

역시 API 함수 중에 LoadIcon이라는 전역 API 함수가 존재합니다. 리소스 ID를 입력받는 버전의 함수 정의에 맞게 파라메터를 준비하여 주시면 됩니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 6. 11. 16:52

요 근래에는 수업 시간에 MDI (Multi Document Interface)에 대해서 실습해 보고 있습니다. 이제까지는 쭉 SDI (Single Document Interface)를 기반으로 작성해 나갔었던 프로그램이 대다수였습니다만, 앞으로 개발하게 될 상용 어플리케이션이나 보편적인 에디터들은 특수한 경우가 아니고서는 대개 MDI로 처리합니다.

MDI와 SDI는 그 모양새와 확장성에서 큰 차이가 드러납니다. 하지만, 프로그래밍 방법이나 클래스의 설정에 있어서도 차이가 있을까요? 아닙니다. SDI 시절 때 프로그래밍하던 방법을 MDI와서도 그대로 쓰십시오. 아무런 문제가 되지 않습니다.

다만, 메인 프레임 윈도우 밑에 딸려있는 자식 윈도우들을 일괄적으로 컨트롤 (Batch Control)하기 위해서 CChildFrame이라는 클래스의 쓰임새를 알아두기만 하면 어려울 것이 하나도 없습니다.

MDI 기반으로 어플리케이션을 작성할 경우, 실제로 SDI때에는 보이지 않았던 몇 가지 항목들이 더 들어가있습니다. 하지만, 어렵게 생각하실 필요는 전혀 없습니다. MDI에서 이상해질 수 있는 인터페이스를 고쳐주기 위하여 등록된 약간의 리소스와 차일드 윈도우들을 띄워줄 수 있는 CChildFrame 클래스의 추가가 전부이니까요.

일단, MDI 기반의 어플리케이션에서는 메인 프레임 아이콘과 도큐먼트 아이콘 두 개로 분리되어 리소스에 저장되어있습니다. 왜냐하면, MDI의 경우 SDI처럼 메인 프레임이 직접 뷰와 도큐먼트를 관리하지 않고 다만 차일드 윈도우들의 디스플레이 영역으로서만 역할을 하기때문이죠. 실질적으로는 차일드 윈도우들이 뷰와 도큐먼트 클래스를 점유하고 있는 것입니다. 그렇기 때문에 차일드 윈도우에 표시해줄 아이콘이 필요한 것이죠.

두 번째로, MDI 기반의 어플리케이션에서는 메뉴 리소스가 두 개가 포함되었습니다. 하나는 차일드 윈도우가 하나 이상 띄워져있을 때의 메인 프레임에 표시될 메뉴이며, 또 하나는 차일드 윈도우가 띄워져있지 않을 때의 빈 메인 프레임 창에서 표시될 메뉴입니다. 이 두 메뉴의 차이는 크게 다르지 않습니다. 뷰/도큐먼트 및 차일드 윈도우에 대한 옵션 설정 메뉴의 유무의 차이입니다.

실제로 수업에서 언급하게 될 클래스는 다름아닌 CChildFrame이란 클래스때문입니다. 이 클래스를 가지고서 여러분은 마음대로, 원하는대로 자유롭게 차일드 윈도우들을 일괄 컨트롤할 수가 있습니다.

이 CChildFrame 클래스는 결국 CMainFrame 클래스와 아주 유사한 꼴입니다. 다만, 윈도우를 로드할 때 차일드 스타일이 미리 적용된 상태에서 로딩이 된다는 점과, 개별적인 프로세스로서 취급되지는 않는 다는 것, 메인 프레임에 종속적이어서 메인 프레임의 실행과 종료에 따라서 띄워진 모든 차일드 프레임 윈도우에도 같은 영향을 준다는 점이 다릅니다.  

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 6. 8. 12:09

이번 Chapter는 MFC 수준에서 쉽고 간편하게 인터넷에 있는 HTML 파일들을 다운로드해오는 방법을 알려드리도록 하겠습니다. 새로운 클래스 두 가지를 알아두셔야 할 필요가 있는데요.

바로, CInternetSession 클래스와 CInternetFile 클래스입니다. 이 두 클래스는 그리 어렵지 않으면서도 친근하게 사용할 수 있는 활용성높은 클래스입니다.

아주 간단한 HTML 파일 액세스 예제를 살펴보도록 합시다.

    CInternetSession isSession;

    CInternetFile* ifFile = NULL; // 포인터일 경우 초기화해야겠죠?

    ifFile = (CInternetFile*)isSession.OpenURL("http://www.naver.com");

위의 세 줄의 코딩은 해당 URL에 액세스할 수 있도록 핸들을 얻어오는 기능을 해줍니다. 이제 남은 것은 실제로 버퍼를 셋팅해서 EOF 시그널 (End Of File Signal)이 검출될 때까지 버퍼로 데이터들을 가져오는 것입니다. 참고로, 한번에 얼마만큼의 바이트를 읽어낼 것인지를 셋팅해 줄 필요가 있습니다.

    ifFile->SetReadBufferSize(4096);

    CString strBuffer;

    for(;;)

    {

      if(!ifFile->ReadString(strBuffer))

        break;

    }

이렇게 얻어진 버퍼는 원하는 대로 다루실 수 있습니다. 특히 CString으로 버퍼를 얻었으니 더욱 간편하겠지요?

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 6. 8. 11:59

일반적으로 공용될 Win32 바이너리 타입의 DLL들은 다른 언어와의 호환성을 위하여 가급적이면 리턴 타입을 Windows가 인지할 수 있는 형태로 컨버젼하여 줄 것을 Microsoft사에서 권장하고 있습니다. 하지만, 어떤것이 Windows에서 인지할 수 있는 것이고 아닌것이고 라는 점을 알아내기가 어려울 것입니다. 실제로, DLL에서 권장되는 데이터 타입들은 주로 핸들을 제외한 32비트형 데이터 타입들이 있으며, ANSI C에서의 데이터 타입들도 권장됩니다.

MSDN 라이브러리나 프로그래밍 바이블 서적을 보면 굉장히 많은 데이터 타입들을 찾아볼 수가 있습니다. 이것들은 모두 ANSI C의 데이터 타입들을 기반으로 하여 재정의된 별명들입니다. 예를 들면 LP라는 키워드가 붙게되는 32비트 데이터 타입들의 경우 Long Pointer를 의미하는 포인터 기호가 붙어있습니다.

다른 언어들도 Win32의 데이터 처리 타입을 기반으로 해서 DLL을 받아들일 수 있도록 설계된 것이므로 충분히 데이터 타입을 어떻게 처리해야 할 것이며 어떻게 언어에 맞게 수용시킬 수 있을지 자체적인 코딩에 의하여 완성되도록 되어있습니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 6. 8. 11:52

실제로 MFC 어플리케이션을 작성하는 데에 있어서 표준 DLL 보다는 MFC 익스텐션 (확장) DLL이 더 많이 쓰여집니다. 그리고 만들기에도 더 간단하고 유용합니다.

MFC DLL 프로젝트로 DLL을 작성할 경우 여러분은 종전의 MFC용 클래스들을 무리하지 않고 편리하게 DLL로 관리할 수가 있습니다. 예를 들면, CObject로부터 상속받아온 클래스를 사용자 정의해서 DLL로 빼내서 관리할 수 있습니다.

여러분이 실제로 MFC 익스텐션 DLL을 만들 때에 DLL 소스 코드에서 클래스의 정의를 하여줄 때에 단지 AFX_EXT_CLASS 매크로 키워드만을 더해주면 완성됩니다.

클래스명을 CExampleTest라고 정의한 경우 MFC 전용 확장 DLL에 알맞게 선언해 주는 방법은 다음과 같습니다. 이 클래스가 CDialog로 부터 상속을 받았다고도 가정하겠습니다.

class AFX_EXT_CLASS CExampleTest: public CDialog { ... }

이렇게 정의해놓으면 나중에 DLL을 빌드하고 나서 DLL을 사용하게 될 메인 어플리케이션의 프로젝트 디렉터리의 DEBUG 디렉터리에 *.LIB 과 *.DLL 파일을 복사하신 후 원하는 대로 링크해서 쓰시면 됩니다. 기존의 링크 방법을 지원합니다. (암시적/명시적)

참고로 이렇게 만들어진 DLL은 특별히 프로토 타입을 셋팅한다든지 할 필요는 없으며 보통때 사용하던 클래스처럼 연결해서 써주면 정상적으로 동작하게 되어있습니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 6. 4. 17:04

보통 클래스는 클래스 그 자체로서만 쓰였을 뿐 별도로 정보를 빼낸다든지, 클래스가 차지하는 메모리 점유율이라든지 하는 등의 어려운 내용들은 아주 알기가 어려웠었습니다. MFC 이전까지만 해도. 하지만, 지금 제가 알려드리는 이 팁은 당장은 아니어도 여러모로 나중에 큰 도움이 될 것입니다.

구조체중에 CRuntimeClass 라는 구조체를 알고 계십니까? 그런데 이상한 게 하나 있죠? 접두사가 분명히 C~ 인데, 왜 구조체냐구요? 실제로 MFC 헤더 선언을 찾아보시면 클래스가 아닌 구조체로 CRuntimeClass가 쓰여져 있습니다.

이 구조체는 CObject와 짝을 이루면서 같이 다니는 파트너라고 할 수 있습니다. 즉, CObject 그 자신은 물론이거니와 그 하위의 수많은 클래스들과 당연히 호환되겠지요.

이 CRuntimeClass가 담게되는 정보는 의외로 알기 어려운 정보들입니다. 실제로, 여러분이 프로그램 소스에서만 등장하는 클래스명을 런타임상에서 따로 빼내오기라는 것은 굉장히 골치아픈일일 겁니다. 하지만, 이 CRuntimeClass를 잘 활용하시면 비단 클래스명뿐만 아니라 클래스에 대한 실행중의 런타임 정보를 다 얻을 수 있습니다.

실제로 어떻게 CRuntimeClass를 사용할 수 있는지 예제를 한 번 봅시다. 이 예제 코드에서는, 현재 아래의 예제 코드가 입력된 위치의 클래스명을 얻어내는 기능을 합니다. 여기서의 프로젝트명은 Amazing이라고 합시다.

    CRuntimeClass* rtciInfo;

    rtciInfo = this->GetRuntimeClass();

    AfxMessageBox(rtciInfo->m_lpszClassName);

만약 위의 코드를 CAmazingView에서 입력했다고 가정합시다. 그러면, 여러분은 CAmazingView의 기능 어딘가에서 CAmazingView라는 내용을 출력하는 메시지 박스를 만날 수 있습니다.

또, 만약 위의 코드를 CAmazingDoc에서 입력했다고 가정합시다. 그러면, 여러분은 CAmazingDoc의 기능 어딘가에서 CAmazingDoc라는 내용을 출력하는 메시지 박스를 만날 수 있습니다.

어떻습니까? 단 세 라인만으로 쉽게 클래스 이름을 얻어내었습니다! 그리고 꼭 클래스명이 아니어도 다른 멤버 변수들을 보시면 좀 더 구체적인 정보들을 활용하실 수가 있습니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 5. 23. 14:28

이미 두 번 이상 메시지 스트림을 가로채는 방법을 강좌에서 설명하였었습니다만, 아직도 이해가 잘 안간다고 느껴지는 분들이 계실법도 해서 여기에 추가 설명을 더합니다.

Windows는 어플리케이션이나 프로세스마다 각각의 개별적인 메시지 큐를 둠으로서 능동적으로 메시지 프로세싱을 구현하도록 설계되었습니다. 이것은 이전의 DOS식의 단방향 런타임 (Single Runtime)과는 대조적인 면입니다.

이런 메시지들은 본래 메시지 큐를 통하여 조건 처리가 되어야 함이 정상이지만 특수한 경우 메시지를 메시지 큐에 들여보내기 전에 빼돌려야 하는 상황이 발생하게 됩니다.

이를 위해서 미리 준비된 오버라이드용 함수가 하나 있습니다. PreTranslateMessage()라는 것으로, 파라메터로는 메시지 태그 구조체가 주어지게 됩니다. 가로챌 메시지 스트림의 양이 많다면 조건문이 길어지게 될 것이며, 간단한 트릭의 수준이라면 조건문이 짧습니다.

간단하게 몇몇의 메시지 가로채기를 구현하고자 한다면 if/else 조건문을, 다량의 메시지 가로채기를 구현하고자 한다면 switch 조건문을 응용하는 것이 좋을 듯 합니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 5. 17. 16:26

어제 DLL에 대해서 처음 만드는 강좌를 하였을 때 아마도 대부분은 감을 잡지 못하고 우왕좌왕하셨을 분들이 많으리라고 예상이 됩니다. DLL이라고 하는 것이 뭐에 써먹는 물건인지 다들 알고 있지만 막상 작성하려고 보니 그 내용이 쉽지가 않아서 걱정을 하시는 것 같습니다. 그래서 DLL을 작성하는데에 있어서 가지게 될 수 있는 의문점을 풀어보고자 합니다.

DLL이라고 하는 것은 그 자체가 Windows에서 다루는 EXE 바이너리와 그 모양새가 닮았습니다. 사실 어떤 프로그래밍 언어이든 어떤 저작 툴이든 EXE 파일은 EXE 파일일 뿐입니다. 그와 마찬가지로 DLL 파일이 어디서 제작되든 어떻게 만들어지는 DLL일 뿐입니다. 어차피 바이너리는 Windows 형식이기 때문에 Windows에서 사용할 수 있는 바이너리 조회 명령어면 다 먹히게 되는겁니다.

DLL을 작성하는데에 있어서 염두해 두실 것은 외부에서 DLL을 액세스할 수 있도록 길문을 틔어줘야만 한다는 것을 잊으면 안됩니다. 그렇지 않는다면 DLL 자체에서밖에는 사용이 안됩니다. 또 한가지는, 다른 언어에서 사용할 수 있도록 하기 위하여 함수 매개변수상에서는 가급적이면 클래스 데이터 형식 말고 ANSI-C 또는 ANSI-C++ 규격에 따르는 데이터 형식을 선언해 주는 것이 좋습니다. 클래스 데이터 형식을 인지하지 못하는 언어가 많기 때문에 특별히 유의해야 하는 것입니다. 그러나 DLL 내부용이라면 상관없습니다.

실제로 여러분은 외부에서 액세스할 수 있도록 길문을 틔워주고픈 함수의 Define (정의) 앞에다가 이렇게만 붙여주면 됩니다.

    extern "C" __declspec(dllimport) 리턴형 함수명(매개 변수, ...);

    extern "C" __declspec(dllexport) 리턴형 함수명(매개 변수, ...);

첫 번째 구문은 DLL을 사용하고자 하는 부분에 지정해주면 되는 것입니다.

두 번째 구문은 접근을 허용해 줄 부분에 지정해 주면 되는 것입니다.

실제로 DLL을 처리하는 설정은 어떻게 해주면 좋을까요? 그것은 여러분의 아이디어를 활용하여 암시적/명시적 연결 중 편리한 것으로 택하여 작성하기만 하면 됩니다. 일반적으로 암시적 연결 방법이 간단한 편입니다. 암시적 연결 방법의 경우 단순히 프로토타입만을 지정해 줌으로서 즉시 사용할 수 있도록 완성됩니다. 명시적 연결 방법의 경우 예외 처리 (Exception)를 사용자 정의할 수 있어서 나름대로 각광을 받는 방법이기는 합니다만 손수 해주어야 할 부분이 많은 편입니다.  

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 5. 15. 17:03

MFC에서 자료를 담는 클래스 중에는 실제로 그 클래스들의 배열을 만든 배열 클래스가 별도록 존재합니다. 그런 배열 클래스들의 기초 템플릿 (형식)이 되는 클래스가 바로 CObArray 클래스입니다. 이 CObArray 클래스를 쓸 줄 알게 되면 나머지는 그 자료형의 특성을 잘 파악하여 CObArray에 사용했던 그대로 이용하면 됩니다.

  • int CObArray::GetSize() const; : 해당 배열에 담겨진 데이터 버퍼들의 수를 구합니다. 예를 들어 5개 배열이 포함되어있으면 여기서는 4를 출력하는데, 리턴되는 정수값은 0부터 시작되는 값입니다.
  • int CObArray::GetUpperBound() const; : 해당 배열의 가장 마지막 배열 번호를 구합니다. 이 함수의 리턴값 역시도 0 기반의 정수값이며, 만약 리턴값이 -1이면 해당 배열 객체에 아무런 내용이 없음을 의미합니다.
  • void CObArray::SetSize(int nNewSize, int nGrowBy = -1); : 해당 배열에 최대로 저장될 수 있는 배열의 갯수를 수동으로 지정합니다. 첫 번째 파라미터는 갯수를 이야기하며, 두 번째 파라미터는 몇 번째 배열부터 자동으로 작업이 이루어질지를 결정하는 부분으로 생략하면 처음부터 데이터가 등록되도록 수행됩니다. 또한 예외 처리를 위하여 throw(CMemoryException); 으로 예외 사항을 던질 수 있습니다.
  • void CObArray::FreeExtra(); : 사용하지 않는 소모되는 나머지 버퍼들을 모두 해제시켜 메모리를 절약할 수 있는 함수입니다.
  • void CObArray::RemoveAll(); : 배열 전체의 데이터를 한 꺼번에 날려버릴 때 사용합니다. 신중을 기해서 사용해야만 합니다.
  • CObject* CObArray::GetAt(int nIndex) const; : nIndex 번째 배열로부터 값을 추출해 옵니다. 리턴형은 CObject* 형으로 배열이 담고 있을 데이터 형이 어떤 것인지에 따라서 다음과 같이 달라지게 됩니다.
    • BYTE CByteArray::GetAt(int nIndex) const;
    • DWORD CDWordArray::GetAt(int nIndex) const;
    • void* CPtrArray::GetAt(int nIndex) const;
    • CString CStringArray::GetAt(int nIndex) const;
    • UINT CUIntArray::GetAt(int nIndex) const;
    • WORD CWordArray::GetAt(int nIndex) const;
  • void CObArray::SetAt(int nIndex, CObject* newElement); : nIndex 번째 배열에 CObject* newElement 데이터를 직접 대입합니다. 어떤 데이터형을 담는 배열인지에 따라서 다음과 같이 달라지게 됩니다.
    • void CByteArray::SetAt(int nIndex, BYTE newElement);
    • void CDWordArray::SetAt(int nIndex, DWORD newElement);
    • void CPtrArray::SetAt(int nIndex, void* newElement);
    • void CStringArray::SetAt(int nIndex, LPCTSTR newElement);
    • void CUIntArray::SetAt(int nIndex, UINT newElement);
    • void CWordArray::SetAt(int nIndex, WORD newElement);
  • CObject*& operator[](int nIndex);
  • CObject* operator[](int nIndex) const; : 이것은 연산자 오버로딩으로서 CStringArray의 사용 예제를 들어서 설명해 보도록 하겠습니다.

    CStringArray m_strADatas;

    m_strADatas.SetSize(50);

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

    {

      switch(i)

      {

      case 0:

        m_strADatas[i].Format("This is an example how to use CStringArray Object. And It is %dst element.", i);

        break;

      case 1:

        m_strADatas[i].Format("This is an example how to use CStringArray Object. And It is %dnd elements.", i);

        break;

      case 2:

        m_strADatas[i].Format("This is an example how to use CStringArray Object. And It is %drd elements.", i);

        break;

      default:

        m_strADatas[i].Format("This is an example how to use CStringArray Object. And It is %dth elements.", i);

        break;

      }

    }


이와 같은 Array 클래스 외에도 리스트 클래스등이 있는데 그것은 다음 강좌에서 설명하겠습니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2002. 5. 10. 16:47

Windows가 나름대로의 비난을 받아오기는 하였지만 사용자나 개발자를 위하여 편리한 기능을 제공한 부분만큼은 비난할 수가 없을 것입니다. 그런 대표적인 예로 WYSIWIG (What You See Is What You Get), 즉 보이는 그대로 얻을 수 있다라는 말을 알아둘 필요가 있을 것입니다.

WYSIWIG을 위해서 동원된 개념들은 굉장히 많이 있습니다. 기존의 비트맵 폰트에서 트루 타입 폰트로, 기존의 비트맵 이미지에서 벡터 이미지로, 통일된 단일 장치에서의 맵핑 모드 전환 등등... 셀 수 없이 많이 있을 것입니다.

실제로 MFC 프로그래밍을 하면 WYSIWIG의 참된 면모를 맛볼 수가 있습니다. 근간에 강좌했던 Device Context에서의 맵핑 모드 (그리기 단위) 변경을 이용하여 해상도와 무관한 출력을 보여주는 것을 확인하였습니다.

실제로 맵핑 모드라고 하는 것은 굉장히 어려운 그래픽 개념 중에 하나이기 때문에 굉장히 생소하거나 쉽게 이해하기가 어려울 수도 있겠지만 그 나름대로의 독창적인 원리가 있다고 생각하시면 쉽습니다.

맵핑 모드를 변경함을 이르는 것은 곧 지도에서의 축도를 가리키는 이야기입니다. 쉬운 예제를 들어, 1:1000 비율의 지도에서의 5cm와 실사의 5cm는 분명히 다른 것입니다. 하지만 이것을 동일 단위로 맞추어 주는 것이 바로 맵핑 모드의 기초 개요입니다. 화면과 프린터사이의 관계를 알아볼까요?

모니터와 프린터는 Windows에서는 닮은꼴의 Device Context를 사용합니다. 실제로, 모니터 또는 프린터의 컬러 프로필 파일을 서로 공유할 수 있으며 전문적인 그래픽 편집가들은 최상의 컬러 프로필 파일을 프린터와 모니터 양쪽에서 공유해서 사용하도록 설정하고 작업을 합니다. 이런 것이 가능한 이유는 양쪽 장치 모두 닮은꼴의 Device Context를 사용하기 때문입니다. 컬러 프로필이라고 하는 것에 대해서는 후단락에서 설명하겠습니다.

여하간, 이러한 형태로 모니터와 프린터는 닮은꼴의 Device Context를 사용하고 있기에 모니터 DC나 프린터 DC나 수행 가능한 작업은 같다라는 의미입니다. 하지만, 문제점이 있습니다.

모니터의 해상도는 평균 1024 * 768 수준입니다. 하지만 프린터의 해상도는 이보다 배를 초과할 수도 있으며 모니터와 비교가 안되는 해상도를 지닙니다. 이로 인해서 데이터를 전송받아서 표현할 때 모니터에서의 픽셀 사이즈와 프린터에서의 픽셀 사이즈는 해상도 차이 때문에 완전히 다른 크기로 보여지게 됩니다. 이것을 통하여 알 수 있는 점은, 픽셀이라는 단위가 가변적인 단위라는 것입니다.

그렇다면 이 문제를 해결하기 위해서는 어떻게 해야 할까요? 다른 것은 없습니다. 모니터 DC쪽에 픽셀 말고 다른 고정적인 또는 불변적인 단위를 사용하도록 하면 될 것입니다. 예를 들면, 인치나, 피트, 센티미터와 같은 것들이 있겠죠.

모니터 DC에 지정함으로서 프린터 DC에도 자동적으로 지정이 가능한 것은 실제로 MFC에서 미리 코딩해 놓은 부분입니다. 즉, 프로그래머는 뷰 클래스의 OnDraw(CDC* pDC)에서 맵핑 모드만을 변경해 주면 되는 것입니다.

맵핑 모드를 변경한다는 것의 결론은 불변인 고정 단위로서 데이터를 표현한다는 데에 있습니다. 또한, 그 단위에 알맞는 좌표 체계를 사용하고 있다는 점에 그 특징이 있습니다.

그리고 아까전에 언급하였던 컬러 프로필이라는 것에 대해서 설명드리겠습니다.

컬러 프로필이라는 것은 일반적으로 모니터나 프린터 드라이버 디스켓 또는 CD-ROM에 포함되어있는 것으로 좀 더 실사와 가까운 색감을 표현하기 위한 색상 데이터 베이스라고 할 수 있습니다.

컬러 프로필은 해당 장치의 성능과 조율을 이루면서 최적화가 되어있어야 제 구실을 합니다. 만약 올바르지 않거나 전혀 연관성이 없는 컬러 프로필을 적용시킨다면 이는 컬러 프로필을 적용시키지 않은것 보다 훨씬 못할 수도 있음을 주의해야 합니다.

모니터 및 그래픽 카드에 적용할 컬러 프로필을 설정할 수 있는 곳은 디스플레이 속성에서의 고급 설정에서 "색 관리" 탭을 선택하면 추가/제거 할 수 있습니다. 여기서 컬러 프로필을 다중으로 사용할 수도 있습니다.

프린터에 적용할 컬러 프로필은 적용할 프린터의 등록 정보 부분에서 찾을 수가 있습니다. 역시 "색 관리" 탭을 선택하면 나타나게 됩니다.

컬러 프로필을 전문적으로 관리하는 프로그램은 Adobe Photoshop의 응용프로그램으로 설치되는 컬러 프로필 에이전트로, 전문적인 컬러 프로필을 설정할 수 있습니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요