String.Format()에서 중괄호는 기본적으로 아래와 같이 값을 치환할 때 사용합니다.
string.Format(@"Value : {0}", 123);
그런데 가끔은 포맷팅 문자열에 중괄호가 들어가야 할때가 있는데 아래처럼 사용하면 "입력 문자열의 형식이 잘못되었습니다."라는 메시지와 함께 FormatException 예외가 발생합니다.
string str = string.Format(@"function() {alert({0});}", @"Alert Message");
이럴 때는 아래와 같이 중괄호를 중첩해서 "{{", "}}" 형식으로 사용하면 예외없이 정상적으로 사용이 가능합니다.
(이때 출력물은 "{", "}"로 됩니다~)
string str = string.Format(@"function() {{alert({0});}}", @"Alert Message");
Posted by Gungume
,
윈도우(Form)가 바탕화면 가장자리에 가까이 가면 자동으로 붙도록 만드는 것은 그다지 어렵지 않습니다.

현재 윈도우의 좌표가 바탕화면 가장자리 좌표와 일정 수준 이상 가깝게 되면 윈도우를 강제로 바탕화면 가장자리 근처로 이동시키는게 로직의 전부입니다.

그러나 C#의 기본 Form 이벤트는 윈도우가 이동이 완료된 후의 이벤트밖에 없습니다. 자석윈도우를 만들려면 윈도우가 이동중일 때의 이벤트가 필요한데 말이죠.

아래 코드는 별다른 로직은 없고 윈도우 메시지를 직접 받아서 처리하는 코드입니다.

간단히 코드를 설명하면 WndProc 함수를 오버라이드해서 WM_WINDOWPOSCHANGING(윈도우가 이동중) 메시지를 받습니다.

그리고 SetDockWindow() 함수를 호출하는데 첫번째 매개변수에는 자석윈도우로 만들 Form을 넘겨줍니다. 두번째 매개변수는 윈도우가 바탕화면 가장자리에 어느정도 가까이 가면 붙도록 할 것인지를 결정하는 수치로 픽셀단위의 정수형 값을 넘겨줍니다. 마지막 매개변수는 WndProc 함수에서 받은 Message 객체를 그대로 전달해줍니다.

SetDockWindow() 함수에서는 Screen.FromHandle()을 이용해서 현재 폼이 위치한 화면의 작업 영역을 얻어옵니다. 이렇게 함으로써 듀얼모니터 지원이 가능합니다.

나머지 코드들은 그냥 좌표 계산이 전부인데 Math.Abs() 함수를 써서 윈도우가 화면안에 있을때나 바깥에 있을 때 모두 자석효과가 가능하도록 처리해줍니다.

public const Int32 WM_WINDOWPOSCHANGING = 0x0046;

[StructLayout(LayoutKind.Sequential)]
public struct WINDOWPOS
{
    public IntPtr hwnd;
    public IntPtr hwndInsertAfter;
    public int x;
    public int y;
    public int cx;
    public int cy;
    public int flags;
}
        
protected override void WndProc(ref Message m)
{
    switch(m.Msg)
    {
        case WM_WINDOWPOSCHANGING:
            SetDockWindow(this, 25, ref m);
            break;
    }
    base.WndProc(ref m);
}

private void SetDockWindow(Form form, int dockMargin, ref Message message)
{
    //현재 Form이 위치한 화면의 작업영역 가져옴(WorkingArea = 작업표시줄을 제외한 영역)
    Rectangle currentDesktopRect = (Screen.FromHandle(form.Handle)).WorkingArea;
            
    WINDOWPOS winPos = (WINDOWPOS)message.GetLParam(typeof(WINDOWPOS));

    //left
    if (Math.Abs(winPos.x - currentDesktopRect.Left) <= dockMargin)
    {
        winPos.x = currentDesktopRect.Left;
    }

    //top
    if (Math.Abs(winPos.y - currentDesktopRect.Top) <= dockMargin)
    {
        winPos.y = currentDesktopRect.Top;
    }

    //right
    if (Math.Abs(winPos.x + winPos.cx - currentDesktopRect.Left - currentDesktopRect.Width) <= dockMargin)
    {
        winPos.x = currentDesktopRect.Right - winPos.cx;
    }

    //bottom
    if (Math.Abs(winPos.y + winPos.cy - currentDesktopRect.Top - currentDesktopRect.Height) <= dockMargin)
    {
        winPos.y = currentDesktopRect.Bottom - form.Bounds.Height;
    }

    Marshal.StructureToPtr(winPos, message.LParam, false);
    message.Result = (IntPtr)0;
}
(사용언어 / 제작툴 / .Net Framework버전 : C# / VS2010 / 2.0)
Posted by Gungume
,
타블렛이나 터치스크린을 사용하면 마우스의 오른쪽버튼 기능을 위해서 롱프레스 기능을 제공합니다.

그러나 가끔은 자신만의 롱프레스 기능 구현을 위해서 이런 기본 기능을 꺼야 하는 경우가 있는데 이럴 때 아래 코드를 사용하면 됩니다.

사용법은 단순히 함수 호출하면서 롱프레스 기능을 끄고 싶은 폼(윈도우, 컨트롤)의 핸들을 첫번째 매개변수로 주고, 두번째 매개변수에 false를 주면 됩니다.(반대로 다시 켜고 싶으면 true를 주면 됩니다.)

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern ushort GlobalAddAtom(string lpString);

[DllImport("user32.dll", SetLastError = true)]
public static extern bool SetProp(IntPtr hWnd, string lpString, IntPtr hData);

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr RemoveProp(IntPtr hWnd, string lpString);

bool TogglePressAndHold(IntPtr hWnd, bool enable)
{
    ushort atomID = 0;
    string tabletAtom = "MicrosoftTabletPenServiceProperty";

    atomID = GlobalAddAtom(tabletAtom);

    if (atomID == 0)
    {
        return false;
    }

    if (enable)
    {
        IntPtr ptr = RemoveProp(hWnd, tabletAtom);
        if (ptr != null)
            return true;
    }
    else
    {
        return SetProp(hWnd, tabletAtom, new IntPtr(1));
    }
    return false;
}
위의 코드는 MSDN에 잇는 코드를 단순히 C#으로 컨버팅한 것입니다. 자세한 정보와 C++, VB 코드는 아래 MSDN을 참고하세요~
(http://msdn.microsoft.com/en-us/library/ms812373.aspx)

첨부파일은 위의 코드를 이용한 샘플 프로그램의 소스이고 그 실행 화면은 아래와 같습니다.
(체크박스의 체크여부에 따라서 폼 위에서 롱프레스 가능 여부가 결정됩니다.)



(사용언어 / 제작툴 / .Net Framework버전 : C# / VS2010 / 2.0)
Posted by Gungume
,
예전에 만들었던 파일날짜 일괄변경 프로그램(http://gungume.com/162)의 초기버전의 스크린샷을 보면 XP와 7에서의 레이아웃이 서로 틀린적이 있었습니다.

이것은 Form의 속성 중 AutoScaleMode와 관련된 것으로 AutoScaleMode는 화면 해상도나 글꼴에 따라서 폼이나 컨트롤의 크기를 자동으로 조절하는 기능입니다.

원래 이 속성은 Font, DPI 등이 다른 환경에서도 적절한 UI를 보여주기 위함인데 파일날짜 일괄변경 프로그램처럼 정확한 위치와 크기로 폼을 디자인할 때는 오히려 이 기능이 악영향을 미칩니다.

파일날짜 일괄변경 프로그램이 레이아웃이 깨졌던 이유는 AutoScaleMode가 Font로 설정되있고 Font는 굴림으로 설정되있는데 영문 윈도우에 해당 Font가 지원이 안되서 다른 Font로 설정되면서 레이아웃이 깨졌던 것입니다.

AutoScaleMode 속성의 기본 값은 Font인데 이 값을 None으로 설정해주면 어느 환경에서나 디자인한 그대로 레이아웃이 유지됩니다.

자세한 정보는 아래 MSDN을 참고하세요~

AutoScaleMode 열거형
http://msdn.microsoft.com/ko-kr/library/system.windows.forms.autoscalemode.aspx

Windows Forms의 자동 배율 조정
http://msdn.microsoft.com/ko-kr/library/ms229605.aspx
Posted by Gungume
,
XP타블렛 에디션, Vista, 7 등에서 터치 스크린이나 타블렛 등을 이용하면 해당 장치들은 마우스와 별도로 처리해주는 과정을 거쳐주면 좀더 깔끔한 프로그램을 만들수 있습니다.

단순히 깔끔한 처리를 넘어서 터치와 펜입력은 마우스와는 이벤트 발생 시점이 조금 틀리므로 이런 차이점을 고려해서 프로그램을 만들어줘야합니다.

대표적으로 차이가 나는 부분이 Down/Up 이벤트로 마우스는 버튼을 누르면 Down 이벤트가 발생하고, 버튼을 놓으면 Up이벤트가 발생합니다. 하지만 터치와 펜 입력은 버튼을 놓는 시점에 Down/Up 이벤트가 동시에 발생합니다.
(혹은 Down 후 Move시에 Down 이벤트 발생)

이런 차이점은 단순한 처리의 경우에는 별다른 문제점이 없습니다. 예를 들어서 버튼의 경우 터치/펜 이벤트도 어차피 Up 이벤트가 발생하는 순간에 Down 이벤트도 발생하므로 버튼이 눌렸다는 이벤트는 발생하므로 마우스와 마찬가지로 버튼의 눌린 것에 대한 이벤트 처리가 가능합니다.

그러나 다음의 경우에 대해서는 문제가 발생합니다.

직접 버튼 컨트롤을 만들고 버튼의 이미지를 Normal, Hover, Press 상태에 따라서 별도로 만들고 마우스/터치/펜 이벤트를 그냥 일반 마우스 이벤트로 처리한다면 마우스는 3가지 상태에 대해서 모두 정상 동작합니다.

하지만 터치/펜의 경우는 정상 동작을 하지 않습니다. 앞서 말했듯이 터치/펜은 Up이벤트가 발생해야 Down이벤트가 발생합니다. 즉 터치/펜을 이용해서 버튼을 누른채로 가만히 있다면 원래는 Press 이미지가 그려져야 하는데 터치/펜은 그 시점에 Down 이벤트가 발생하지 않으므로 Press 이미지를 그리지 못합니다.
(이런 문제점은 Vista, 7 등에서 기본 버튼 컨트롤 위에서도 발생합니다.)

MS에서는 이런 문제를 해결할 수 있도록 터치/펜에 대한 패킷데이터를 바로 받을 수 있는 방법을 제공하는데 Microsoft.Ink.Dll에 들어있는 RealTimeStylus가 그것입니다.

RealTimeStylus는 XP Tablet Edition을 위한 TabletSDK에 처음 들어있었고, 비스타(닷넷프레임워크 3.0)에서부터는 기본적으로 들어있습니다. 이것을 사용하면 패킷데이터를 바로 받을 수 있기 때문에 최종 결과물을 보면 일반 마우스처럼 동작하도록 만들 수 있고 단순히 위의 내용에 대한 해결방법외에 타블렛, 터치에 대한 다양한 정보를 얻을 수 있습니다.

참고로 Microsoft.Ink.Dll은 몇가지 버전이 있는데 단순히 위에 열거한 문제를 해결하기 위해서는 TabletSDK에 들어있는1.7버전을 사용해도 됩니다. 하지만 샘플에서는 마우스/터치/타블렛을 지원하는 코드를 포함하느라 비스타에 들어있는 6.0버전을 사용했습니다.
(참고로 7에 들어있는 6.1 버전은 멀티터치 관련한 내용도 들어있습니다.)

아래 링크는 TabletSDK와 Microsoft.Ink.Dll 버전 선택에 관한 MSDN 문서입니다.

RealTimeStylus의 간단한 샘플에 대한 코드는 다음 포스트에서 다루겠습니다.
Posted by Gungume
,


개인적으로 네이트온의 쪽지기능을 많이 싫어해서 만든 프로그램입니다.

싫어하는 이유는 많이 있겠지만 YUE님의 나는 네이트온 쪽지창을 싫어한다.(http://yue.co.kr/66)라는 글이 모든 것을 설명해주는 것 같습니다.

사용법은 간단합니다.

프로그램을 실행하면 위와 같은 화면이 나오는데 기본적으로는 "특정 사용자만 차단"이 해제되어 있고, 이것이 해제되어 있다면 모든 쪽지가 차단됩니다.

그리고 특정 사용자만 차단하고 싶다면 위의 화면과 같이 "특정 사용자만 차단" 버튼을 체크하고, 사용자 이름 입력 부분에 차단을 하고 싶은 사용자의 이름을 입력하고 엔터키를 누르거나 "사용자 추가" 버튼을 누르면 차단할 사용자가 추가됩니다.

프로그램 시작과 동시에 별다른 설정없이 바로 차단이 동작합니다. 그리고 프로그램의 X버튼을 누르면 자동으로 트레이로 이동됩니다.(프로그램 종료는 트레이에서 가능합니다.)

마지막으로 "특정 사용자만 차단" 체크여부와 추가된 사용자는 프로그램 종료시 자동으로 user.dat라는 파일에 저장되고 이 정보를 이용해서 다음 실행시 해당 정보를 이용해서 프로그램이 실행됩니다.

※ 네이트온 프로토콜 등을 분석해서 만든 것이 아니고 쪽지가 오면 바로 꺼버리는 방식으로 만들었으므로, 프로그램을 사용한다면 쪽지가 왔었는지 여부를 알 수 없으니 사용상의 주의 필요함.(메시지함에 직접 들어가면 확인 가능)

(사용언어 / 제작툴 / .Net Framework버전 : C# / VS2010 / 2.0)

※ 아이콘
Posted by Gungume
,

프로젝트 클리너를 업데이트 했습니다. 기본 사용법은 0.2 버전이랑 동일합니다.

우선 기존 프로그램은 닷넷의 기본 파일/폴더 검색 메소드를 반복해서 사용시 상당한 속도 저하가 있길래 이 부분을 개선했습니다.


또한 위의 화면처럼 "확인 후 정리하기" 기능을 통해서 삭제하기 전에 삭제될 목록을 확인 후 원하는 목록만 삭제하는 기능을 추가했습니다.

"확인 후 정리하기" 에서 "정리하기" 버튼을 눌러서 정리한 이후에는 삭제 실패한 항목을 목록에 다시 보여줍니다
(목록을 다시 보여줄 때에는 처음부터 체크해제를 해놓은 항목에 대해서는 보여주지 않습니다)

(사용언어 / 제작툴 / .Net Framework버전 : C# / VS2008 / 2.0)

이전버전 받기

※ 정리할 목록의 기본값은 C언어쪽 프로젝트에 맞게 해놓은 목록입니다. 기본 목록을 가지고 C# 프로젝트에 사용하면 '*.RES' 항목 때문에 리소스 파일이 삭제되니 주의 바랍니다.

Posted by Gungume
,
제가 올렸던 WMI라이브러리,  MultipleSearchPattern 라이브러리를 보시면 chm 파일로 라이브러리에 대한 도움말 파일이 있는데 Sandcastle이라는 것을 이용해서 이 도움말 파일을 만드는 방법을 설명하겠습니다.

우선 이 작업을 위해서는 XML주석이 필요한데 컴파일 결과로 XML 파일을 생성해야 합니다.
(XML 주석과 관련해서는 http://msdn.microsoft.com/ko-kr/library/b2s063f7.aspx 를 참고하세요...)

C#의 프로젝트 옵션에서 Build -> Output 항목을 보면 "XML documentation file" 항목이 기본적으로 체크되있지 않은데 아래 화면처럼 체크를 한 뒤에 컴파일을 하면 XML 주석 내용이 *.XML 파일로 출력됩니다.

이제 이 xml 파일과 dll 등 프로젝트 결과물은 도움말 파일 만드는데 사용합니다.

우선 아래 2개의 사이트에서 파일을 받아서 설치합니다.

각각 대략적으로 설명하면 Sandcastle은 도움말 파일을 만들기 위한 라이브러리, SHFB(Sandcastle Help File Builder)은 도움말 파일을 만드는 툴 정도로 생각하시면 됩니다.
(이외에 chm 파일을 만들기 위해서 "HTML Help Workshop"가 필요하지만 vs 등을 설치하면 기본적으로 설치되니 별도의 설치는 필요 없을 듯 합니다. 혹시 설치가 안되있다면 인터넷에서 그냥 받아서 설치하면 됩니다.)

설치 후에 생성된 시작메뉴에서 "Sandcastle Help File Builder GUI"를 실행합니다.

프로그램 실행 후에 File -> New Project나 툴바메뉴에서 가장 왼쪽 아이콘을 눌러서 새프로젝트를 생성합니다.
(도움말 파일을 만들기 위한 정보, 결과물이 저장될 수 있도록 작업 경로를 만드는 작업으로 적당한 폴더를 정해주고파일명을 적어준 후 저장 버튼을 누릅니다.)

프로젝트를 만들고 나면 아래 화면의 오른쪽에 보이는 것처럼 Project Explorer에서 Documentation Sources 항목이 있는데 여기서 마우스 오른쪽 버튼을 눌러서 Add Documentation Sources를 눌러서 위에서 설명했던 xml 파일과 dll 등의 프로젝트 결과물을 추가해줍니다.
(이외에 Visual Studio의 솔루션, 프로젝트 파일 등 다른 방법으로도 추가가 가능합니다.)

파일 추가가 끝나면 아래 화면의 왼쪽에 있는 Project Properties에서 적당히 설정을 해주고 Visual Studio에서 볼 수 있는 빌드 아이콘을 클릭해서 빌드를 합니다.
(설정은 기본적으로 Language 정도만 해주면 될 것 같고 때에 따라서 포맷, 스타일 정도를 지정해 주면 될 것 같네요...그리고 빌드 버튼은 Documentation -> Build Project 메뉴로도 가능합니다.)

빌드가 성공하면 아래처럼 빌드가 성공했다는 메시지가 나옵니다.
(빌드 시간은 좀 걸립니다.)

빌드가 성공적으로 끝나면 처음에 프로젝트 만들었던 폴더를 보면 Documentation.chm 파일로 도움말 파일이 완성되고 열어보면 아래처럼 결과가 나옵니다.

참고로 위 샘플에 쓰인 코드는 아래와 같습니다. XML 주석 부분이랑 결과를 비교해보세요.

Posted by Gungume
,

프로젝트 클리너를 업데이트했습니다. 일단 닷넷으로 만들었습니다.

주요 업데이트 내용은 폴더를 정리할 수 있는 기능을 추가했고 파일, 폴더를 선택해서 정리가 가능합니다.

파일과 폴더 목록에는 와일드카드(*, ?) 사용이 가능하며 자세한 내용은 아래 msdn의 searchPattern 부분을 참고하면 될 것 같습니다.

또한 정리할 파일, 폴더의 목록과 선택여부를 data.xml파일에 저장하도록 했으며 xml 구조는 아래와 같습니다.

data.xml 파일이 없는 경우나 파일을 읽어오는 과정에서 오류가 발생하면 위의 스크린샷에 있는 설정이 기본 설정으로 적용되어서 사용이 가능합니다.
 

   
      *.ncb 
      *.opt 
      *.plg 
      *.obj 
      *.sbr 
      *.bsc 
      *.idb 
      *.pdb 
      *.ilk 
      *.exp 
      *.pch 
      *.res 
   
   
      DEBUG 
      RELEASE 
   

(사용언어 / 제작툴 / .Net Framework버전 : C# / VS2008 / 2.0)

이전 버전 받기
최신 버전 받기

※ 정리할 목록의 기본값은 C언어쪽 프로젝트에 맞게 해놓은 목록입니다. 기본 목록을 가지고 C# 프로젝트에 사용하면 '*.RES' 항목 때문에 리소스 파일이 삭제되니 주의 바랍니다.
Posted by Gungume
,


H님의 의견을 반영해서 프로그램을 약간 업데이트했습니다.

업데이트 내용은 폴더의 날짜도 변경 가능하게 했습니다.
(H님의 다른 의견인 프로그램 자체에서 목록을 추가하는 기능은 C#의 기본 기능상으로는 폴더와 파일을 따로 추가해야되고 폴더가 다중선택이 안되는 문제로 일단 보류 상태입니다.)

목록에 폴더를 추가한 경우에는 일괄변경 하기전에 해당 폴더를 닫아주시기 바랍니다. 탐색기 등에서 폴더를 열어놓으면 윈도우에서 해당 폴더를 사용중이라는 오류가 나옵니다.
(폴더를 닫은 이후에도 같은 오류가 발생되면 조금 시간이 지나고 재시도하시면 됩니다.)

(사용언어 / 제작툴 / .Net Framework버전 : C# / VS2008 sp1 / 2.0)

이전 버전 받기


Posted by Gungume
,