2015년 8월 7일 금요일

c# Webbrowser Control에서 CSS 웹사이트 적용하기

회사에서 진행 중인 프로젝트에서 c# Application에서 Webbrowser Control을 사용하여 클라우드 서버와 연동하는 프로젝트를 진행하게 되었다.

c# 에서 기본 제공하는 Webbrowser Control은 기본이기도 하지만 사용하기도 편한 장점이 있지만
큰 단점이 하나 있는데 CSS style sheet 가 제대로 적용이 되지 않는다는 점이다.


왼쪽이 익스플로러 화면이며, 오른쪽이 Webbrowser Control을 이용한 테스트 프로그램이다.

예상하는 문제 원인으로는 아마도 해당 컨트롤이 IE7으로 인식 되기 때문인데 실제로 윈도우에 IE8이상이 설치되어 있다고 해도 무조건 IE7 엔진으로 구동되기 때문에 스타일 시트가 제대로 적용되지 않는 것 같다.

이에대한 대책으로 .net Wrapping 된 Webkit 엔진 라이브러리를 사용하였으나 또다른 문제가 발생하였는데. Flash나 HTML5가 완전히 구현되지 않았다는 점이다.

HTML5 Video 부분 스펙이 완전히 결정된지 얼마 되지 않았고. 대부분의 Wrapper library들이 마지막업데이트가 된지 제법 되었기 때문에 대응이 되지 않은 것으로 보인다.

늘 그렇듯이 구글검색을 통하면 왠만한 솔루션이 있기에 이를 해결하기 위한 방법을 찾아보자.



구글링으로 찾아보니 FEATURE_BROWSER_EMULATION 이라는 것을 설정해서 해당 응용프로그램의 Webbrowser를 이용하면 된다고 한다.

         public Form1()
        {
            SetBrowserFeatureControl();
            InitializeComponent();
        }
       
        private static void SetBrowserFeatureControl()
        {
            // http://msdn.microsoft.com/en-us/library/ee330720(v=vs.85).aspx
            // WebBrowser Feature Control settings are per-process
            var fileName = System.IO.Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);
            // make the control is not running inside Visual Studio Designer
            if (String.Compare(fileName, "devenv.exe", true) == 0 || String.Compare(fileName, "XDesProc.exe", true) == 0)
                return;
            SetBrowserFeatureControlKey("FEATURE_BROWSER_EMULATION", fileName, GetBrowserEmulationMode());
        }

        private static void SetBrowserFeatureControlKey(string feature, string appName, uint value)
        {
            using (var key = Registry.CurrentUser.CreateSubKey(
                String.Concat(@"Software\Microsoft\Internet Explorer\Main\FeatureControl\", feature),
                RegistryKeyPermissionCheck.ReadWriteSubTree))
            {
                key.SetValue(appName, (UInt32)value, RegistryValueKind.DWord);
            }
        }
        private static UInt32 GetBrowserEmulationMode()
        {
            int browserVersion = 7;
            using (var ieKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Internet Explorer",
                RegistryKeyPermissionCheck.ReadSubTree,
                System.Security.AccessControl.RegistryRights.QueryValues))
            {
                var version = ieKey.GetValue("svcVersion");
                if (null == version)
                {
                    version = ieKey.GetValue("Version");
                    if (null == version)
                        throw new ApplicationException("Microsoft Internet Explorer is required!");
                }
                int.TryParse(version.ToString().Split('.')[0], out browserVersion);
            }
            // Internet Explorer 10. Webpages containing standards-based !DOCTYPE directives are displayed in IE10 Standards mode. Default value for Internet Explorer 10.
            UInt32 mode = 10000;
            switch (browserVersion)
            {
                case 7:
                    // Webpages containing standards-based !DOCTYPE directives are displayed in IE7 Standards mode. Default value for applications hosting the WebBrowser Control.
                    mode = 7000;
                    break;
                case 8:
                    // Webpages containing standards-based !DOCTYPE directives are displayed in IE8 mode. Default value for Internet Explorer 8
                    mode = 8000;
                    break;
                case 9:
                    // Internet Explorer 9. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode. Default value for Internet Explorer 9.
                    mode = 9000;
                    break;
                default:
                    // use IE10 mode by default
                    break;
            }
            return mode;
        }


주요 코드를 복사해 보았다.

생성자에 보면 SetBrowserFeatureControl 메소드가 call 되는 것을 볼 수 있는데 이부분이
FEATURE_BROWSER_EMULATION  를 셋팅해주는 곳이다.

하나하나 소스코드를 따라 가면서 확인해 보면

현재 실행중인 프로세스 이름을 가져오는 부분이 있는데 이부분은 비쥬얼 스튜디오내에서 실행 중인 경우 , 즉 아마도 디자이너에서 보여질때 생성되기 때문에 예외처리인듯 하며.

그다음 줄인 아래에 기록한 메소드를 보자. 
SetBrowserFeatureControlKey("FEATURE_BROWSER_EMULATION", fileName, GetBrowserEmulationMode());

해당 메소드를 보면 우선 GetBrowserEmulationMode() 메소드에서 현재 브라우져의 버전을 알아오고 브라우져 버전에 맞는 에뮬레이션 모드값을 가져온다. 메소드 내용을 살펴보면 알겠지만
우선 레지스트리에서 svcVersion 이나 Version 값을 찾아서 해당 버전에 대응되는 모드값을 반환한다.

그 모드 값을 인자로 하여 이제 FEATURE_BROWSER_EMULATION을 셋팅하는데, 결국은 레지스트리에 기록하는 것이다.

SetBrowserFeatureControlKey() 메소드의 내용을 확인하면 아래의 레지스트리에
Software\Microsoft\Internet Explorer\Main\FeatureControl\

FEATURE_BROWSER_EMULATION 이라는 서브키를 생성하고 거기에 현재 실행중인 파일이름, 아까 구한 브라우져 모드값을 등록한다.

실제로 등록이 잘되는지 실행해서 확인해 보자.



레지스트리 에디터로 확인해 보니 현재 실행중인 프로그램으로 모드값이 기록되어있다.

이제 프로그램으로 적용이 되는지 확인해 보자.






이전과 다르게 정상적으로 렌더링이 된 것을 확인 할 수 있다.




댓글 없음:

댓글 쓰기