2009/02/14 01:21

Visual Studio추가기능(Add-In) 만들기 - Part2

2009/02/11 - [VS2008,2005,2003] - Visual Studio추가기능(Add-In) 만들기 - Part1
에 이어서 VS에 간단한 추가기능을 추가해보도록 하겠습니다.

제일중요한 IDTExtensibility2와 IDTCommandTarget의 인터페이스에 대한 정리는 제일 나중에 정리하도록 하고..
일단 툴바메뉴에 버튼을 추가해보죠.


IDTExtensibility2의 인터페이스메서드중 하나인 OnConnection메서드에 아래와같은 코드를 입력해주시고
SetToolBar()라는 함수도 추가해주세요. SetToolBar는 실제 버튼을 등록하는 코드를 서브루틴으로 빼둔겁니다.

  public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
  {
   _applicationObject = (DTE2)application;
   _addInInstance = (AddIn)addInInst;
            switch (connectMode)
            {
                   
                case ext_ConnectMode.ext_cm_Startup:
                    SetToolBar();
                    break;

                case ext_ConnectMode.ext_cm_AfterStartup: 
                    SetToolBar();
                    break;

                case ext_ConnectMode.ext_cm_CommandLine:
                    break;

                case ext_ConnectMode.ext_cm_External:
                    break;

                case ext_ConnectMode.ext_cm_Solution:
                    break;

                case ext_ConnectMode.ext_cm_UISetup:
                    break;

                default:
                    break;
            }
  }

        /// <summary>
        /// 표준Toolbar에 버튼을 등록
        /// </summary>
        private void SetToolBar()
        {
            CommandBar stdCmdBar;
            CommandBarButton cmdBarBtn;
            object[] contextGUIDS = new object[] { };

            //커맨드가 등록되어 있지않다면 새로 등록
            if (ToolbarCommand == null)
            {
                ToolbarCommand = _applicationObject.Commands.AddNamedCommand(_addInInstance,
                  "ANewComment", "코멘트추가", "코멘트를 추가해줍니다.", true, 59, ref  contextGUIDS,
                      (int)vsCommandStatus.vsCommandStatusSupported 
                     | (int)vsCommandStatus.vsCommandStatusEnabled);
            }

            //표준툴바의 객체를 취득
            stdCmdBar =
            (Microsoft.VisualStudio.CommandBars.CommandBar)((Microsoft.VisualStudio.CommandBars.CommandBars)_applicationObject.CommandBars)["Standard"];

            //표준툴바에 버튼을 추가
            stdCmdBarCtl = (Microsoft.VisualStudio.CommandBars.CommandBarControl)ToolbarCommand.AddControl(stdCmdBar, stdCmdBar.Controls.Count + 1);

            //버튼에 캡션설정
            stdCmdBarCtl.Caption = "이거 누르면 코멘트가 추가됩니다.";

            //버튼을 아이콘으로 설정
            cmdBarBtn = (CommandBarButton)stdCmdBarCtl;
            cmdBarBtn.Style = MsoButtonStyle.msoButtonIcon;
        }


일단 이것만 하고 실행(F5)를 누르고 디버깅해주시면 아래 그림과 같이 툴바 제일끝에 스마일버튼이 추가된걸 보실수가 있습니다.



근데!!버튼을 누를수가 없네요.
IDTCommandTarget의 인터페이스메서드중 하나인 QueryStatus메서드에 아래와같은 코드를 입력해주세요.
빨간 부분은 프로젝트를 만들때 사용했던 추가기능의 이름을 넣어주세요.


  public void QueryStatus(string commandName, vsCommandStatusTextWanted neededText, ref vsCommandStatus status, ref object commandText)
  {
   if(neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone)
   {

                //커맨드명과 현재 활성화된 창의 문서가 Document일 경우에만 사용가능하다는 신호를 보냄
                if (commandName == "MyTestAddin1.Connect.ANewComment" && _applicationObject.ActiveWindow.Type == vsWindowType.vsWindowTypeDocument)
                 {
                    status = (vsCommandStatus) vsCommandStatus.vsCommandStatusEnabled | vsCommandStatus.vsCommandStatusSupported;
                    return;
                 }

   }
  }

QueryStatus메서드는 VS가 자신의 상태가 변하면 각 커맨드들에 사용가능한 상태인지 요청하게 됩니다.
QueryStatus메서드에서 현재 VS의 상황을 파악하여 사용가능여부를 반환합니다.
예를들어 위의 코드에서는 '커맨드명과 현재 활성화된 창의 문서가 Document일 경우에만 사용가능하다는 신호를 보냄'이 상황이 됩니다.

제가 현재 열려진 창의 문서가 Document일 경우에만 사용가능하다는 신호를 보냄이란 조건을 설정한 이유는 스타트페이지가 열려진 상태에서 버튼이 눌러지게 되면 코멘트를 넣을곳이 없기때문에 에러를 발생시키기 때문이죠..
물론 코멘트를 넣어줄때 체크를 하면되지만 유저인터페이스를 고려해서 쓸수 없는 상황에는 아예 안눌려지게 하기위함입니다..
(위의 조건도 완벽한 상태가 아닙니다.실은 vsWindowTypeDocument라는건 파일의 종류와 상관없이 편집가능한 문서-소스코드,HTML,CSS,XML등 모든 문서-를 의미합니다.)



자 이제 마지막으로 버튼을 눌렀을때 문서에 코멘트를 넣는 코드를 추가해보겠습니다.
IDTCommandTarget의 인터페이스메서드중 하나인 Exec메서드에 아래와같은 코드를 입력해주세요.

  public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
  {

   handled = false;
   if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
   {
                switch (commandName) //스위치를 사용하여 불려진 커맨드를 체크.(혹시 하나의 추가기능에 버튼이 여러개 있을수도 있으니까 스위치를 사용합니다.)
                {
                    case "MyTestAddin1.Connect.ANewComment":
                        //현재 열려진 창이 문서인지 재확인을 하고
                        if (_applicationObject.ActiveWindow.Type == vsWindowType.vsWindowTypeDocument)
                        {
                            //열려진 문서의 인스턴스를 취득해서
                            TextDocument textDoc = (TextDocument) _applicationObject.ActiveWindow.Document.Object("TextDocument");
                            textDoc.StartPoint.CreateEditPoint(); //커서위치를 가져오고
  
                            //커맨드를 삽입하고
                            textDoc.Selection.Insert(string.Format("//{0}에 입력되었습니다.",DateTime.Now.ToString()), 0); 

                            //보기좋게 하기위해 개행문자를 넣어줌...
                            textDoc.Selection.EndOfLine(true);
                            textDoc.Selection.NewLine(1);

                            handled = true;
                        }
                        return;

                    default:
                        break;
                }
   }


}


자!!! 이제 다 만들어졌습니다.
다시 실행버튼을 누르시고 대충 아무 cs파일을 여시고.. 파일을 여시면 버튼이 활성화되는걸 보실수 있을겁니다.
그리고 버튼을 누르시면 아래처럼 자동으로 코멘트가 들어가 있을겁니다.



일단 오늘 시간이 좀 늦었으니 담번에 IDTExtensibility2와 IDTCommandTarget에 대해서랑 어떻게 추가기능을 배포할것인지를 정리하도록 하겠습니다..-.-;;


내용 추가
아래 소스코드도 IDTExtensibility2의 OnDisconnection메서드에 집어넣어주세요. 아래의 소스코드는 추가기능이 언로드될때 커맨드와 버튼을 삭제해줄때 사용합니다.이걸 집어넣지 않으면 추가기능을 활성화, 비활성화할때 에러를 발생시킬수 있거든요..^^;
깜박하고 빼먹었습니다..

  public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom)
  {

            //추가기능이 언로드될 등록한 버튼과 커맨드를 삭제
            try
            {
                if (disconnectMode == ext_DisconnectMode.ext_dm_UserClosed)
                {
                    if (stdCmdBarCtl != null)
                    {
                        stdCmdBarCtl.Delete(null);
                        stdCmdBarCtl = null;

                        ToolbarCommand.Delete();
                        ToolbarCommand = null;
                    }

                    if (MenuToolCommand != null)
                    {
                        MenuToolCommand.Delete();
                        MenuToolCommand = null;
                    }
                }
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.ToString());
            }
  }

저작자 표시 비영리 변경 금지
Trackback 0 Comment 0