当WebBrowser控件(CDHtmlDialog自动创建了WebBrowser控件)加载的网页中含有错误Javascript代码时默认情况下控件会弹出错误信息提示对话框,相对于用户体验来说这样的提示完全不是开发人员想要的,针对这个问题有两个解决方案,一是完全屏蔽掉错误提示,二是控制错误的提示并且记录错误信息同时也可以控制出现错误后Javascript是否继续执行。

1、屏蔽错误信息提示

1
m_pBrowserApp->put_Silent(VARIANT_TRUE);

在CDHtmlDialog::OnInitDialog()的代码中首先了创建WebBrowser控件,然后把控件的Browser对象赋值给m_pBrowserApp(这是CDHtmlDialog完成的不需要自己处理)。WebBrowser的put_Silent函数在官方给出的说明是禁用所有的对话框,但例外情况是它不会影响SSL安全认证需要的进示对话框。绝大多数情况下这就可以解决问题了,记得很久以前我遇到过一种情况就是虽然调用了put_Silent但是还是有极个别的js错误是无法屏蔽掉的依然会显示出来(在网页含有嵌套页面时会错误无法屏蔽,不知道是否还有其它情况),现在找不到这样的网页了,如果谁遇到这种情况了建议给我发上个URL让我也重温一下当年阳光灿烂的时刻。

2、控制错误提示并进行记录

  这要比第一种方法复杂上许多,简短的来说就是自定义COleControlSite类并实现IOleCommandTarget接口,IOleCommandTarget接口是错误控制的关健,错误发生时会触发此接口的Exec函数并为nCmdID参数赋值为OLECMDID_SHOWSCRIPTERROR,这样就可以得到错误信息了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
IOleCommandTarget : public IUnknown
    {
    public:
        virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE QueryStatus(
            /* [unique][in] */ __RPC__in_opt const GUID *pguidCmdGroup,
            /* [in] */ ULONG cCmds,
            /* [out][in][size_is] */ __RPC__inout_ecount_full(cCmds) OLECMD prgCmds[  ],
            /* [unique][out][in] */ __RPC__inout_opt OLECMDTEXT *pCmdText) = 0;
         
        virtual HRESULT STDMETHODCALLTYPE Exec(
            /* [unique][in] */ __RPC__in_opt const GUID *pguidCmdGroup,
            /* [in] */ DWORD nCmdID,
            /* [in] */ DWORD nCmdexecopt,
            /* [unique][in] */ __RPC__in_opt VARIANT *pvaIn,
            /* [unique][out][in] */ __RPC__inout_opt VARIANT *pvaOut) = 0;
         
    };
    

现在我们开始实现自定义的COleControlSite

1
2
3
4
5
6
7
8
9
10
11
12
13
class CMyControlSite : public COleControlSite
 
public
    CMyControlSite(COleControlContainer *pCntr):COleControlSite(pCntr) {}
 
protected
 
    DECLARE_INTERFACE_MAP() 
    BEGIN_INTERFACE_PART(OleCommandTarget, IOleCommandTarget) 
        STDMETHOD(QueryStatus)(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText); 
        STDMETHOD(Exec)(const GUID* pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG* pvaIn, VARIANTARG* pvaOut); 
    END_INTERFACE_PART(OleCommandTarget) 
1
 

MFC提供了很多宏用于简化COM相关功能的开发,对COM接口的实现方式在MFC中具体体现方式是内嵌类,背后的设计思想是COM聚合,每个接口都产生一个内嵌类,所有的接口都聚合到外层的类。DECLARE_INTERFACE_MAP()  实际上就是定义一个数组以及查询操作,BEGIN_INTERFACE_PART定义一个命名为XOleCommandTarget的内嵌类(内嵌类的命名规则是XName)并定义IUnknown接口的三个方法AddRef、Release、QueryInterface。END_INTERFACE_PART定义一个m_xOleCommandTarget的成员类型为XOleCommandTarget(定义的成员命名规则就是m_xName),并把XOleCommandTarget类声明为外层类的友元类在示例中外层类指CMyControlSite。

STDMETHOD宏定义为virtual __declspec(nothrow) HRESULT __stdcall,该宏定义函数为虚函数返回值为HRESULT,函数调用约定为__stdcall,并且在此函数上禁止异常。__declspec(nothrow)用定告诉编译器它修饰的函数以及此函数调用的函数不会产生C++异常调用从可以优化代码性能和代码尺寸(默认情况下C++编译器为了进行异常处理会在拥有throw调用的函数中自动生成相关的异常处理代码)。通常情况下HRESULT返回值就表达了错误信息,HRESULT是个32位值,不同的位域用于不同的目的,也可以使用自定义的位域,具体的信息可以参考http://en.wikipedia.org/wiki/HRESULT。由于COM本身的语言中立性所以不应该在COM组件对外公布的信息中掺杂特定语言相关的特性。如果需要提供更详尽的错误信息那么应该实现COM的IErrorInfo接口。言归正传以下是CMyControlSite的类实现代码

BEGIN_INTERFACE_MAP(CMyControlSite, COleControlSite)   INTERFACE_PART(CMyControlSite, IID_IOleCommandTarget, OleCommandTarget)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<em id="__mceDel"><em id="__mceDel">END_INTERFACE_MAP() 
 
 
HRESULT CMyControlSite::XOleCommandTarget::Exec 
(const GUID* pguidCmdGroup, DWORD nCmdID, 
 DWORD nCmdexecopt, VARIANTARG* pvaIn, VARIANTARG* pvaOut ) 
    HRESULT hr = OLECMDERR_E_NOTSUPPORTED; 
    //return S_OK; 
    if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup, CGID_DocHostCommandHandler)) 
    
 
        switch (nCmdID)  
        
 
        case OLECMDID_SHOWSCRIPTERROR: 
            
                IHTMLDocument2*             pDoc = NULL; 
                IHTMLWindow2*               pWindow = NULL; 
                IHTMLEventObj*              pEventObj = NULL; 
                BSTR                        rgwszNames[5] =  
                {  
                    <span>SysAllocString(L"errorLine"), </span><br><span>SysAllocString(L"errorCharacter"), </span><br><span>SysAllocString(L"errorCode"), </span><br><span>SysAllocString(L"errorMessage"), </span><br><span>SysAllocString(L"errorUrl")</span>
                }; 
                DISPID                      rgDispIDs[5]; 
                VARIANT                     rgvaEventInfo[5]; 
                DISPPARAMS                  params; 
                BOOL                        fContinueRunningScripts = true
 
                params.cArgs = 0; 
                params.cNamedArgs = 0; 
                 
                hr = pvaIn->punkVal->QueryInterface(IID_IHTMLDocument2, (void **) &pDoc);     
                  
                hr = pDoc->get_parentWindow(&pWindow); 
                pDoc->Release(); 
                 
                hr = pWindow->get_event(&pEventObj); 
                 
                for (int i = 0; i < 5; i++)  
                {   
                     
                    hr = pEventObj->GetIDsOfNames(IID_NULL, &rgwszNames[i], 1,  
                        LOCALE_SYSTEM_DEFAULT, &rgDispIDs[i]); 
                 
                    hr = pEventObj->Invoke(rgDispIDs[i], IID_NULL, 
                        LOCALE_SYSTEM_DEFAULT, 
                        DISPATCH_PROPERTYGET, ¶ms, &rgvaEventInfo[i], 
                        NULL, NULL); 
                    //可以在此记录错误信息</em></em>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
                    //必须使用SysFreeString来释放SysAllocString分配的内存,SysAllocString在分配的内存中记录了字符的长度
                    SysFreeString(rgwszNames[i]); 
                
 
                // At this point, you would normally alert the user with  
                // the information about the error, which is now contained 
                // in rgvaEventInfo[]. Or, you could just exit silently. 
 
                (*pvaOut).vt = VT_BOOL; 
                if (fContinueRunningScripts) 
                
                    // 在页面中继续执行脚本
                    (*pvaOut).boolVal = VARIANT_TRUE; 
                
                else
                
                    // 停止在页面中执行脚本 
                    (*pvaOut).boolVal = VARIANT_FALSE;    
                }  
                break
            
        default
            hr =OLECMDERR_E_NOTSUPPORTED;
            break
        
    
    else
    
        hr = OLECMDERR_E_UNKNOWNGROUP;
    
    return (hr); 
 
 
ULONG FAR EXPORT CMyControlSite::XOleCommandTarget::AddRef()  
{  
    METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)  
        return pThis->ExternalAddRef();  
}  
 
 
ULONG FAR EXPORT CMyControlSite::XOleCommandTarget::Release()  
{  
    METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)  
        return pThis->ExternalRelease();  
}  
 
HRESULT FAR EXPORT CMyControlSite::XOleCommandTarget::QueryInterface(REFIID riid, void **ppvObj)  
{  
    METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)  
        HRESULT hr = (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj);  
    return hr;  
 
STDMETHODIMP CMyControlSite::XOleCommandTarget::QueryStatus(  
    /* [unique][in] */ const GUID __RPC_FAR *pguidCmdGroup,  
    /* [in] */ ULONG cCmds,  
    /* [out][in][size_is] */ OLECMD __RPC_FAR prgCmds[ ],  
    /* [unique][out][in] */ OLECMDTEXT __RPC_FAR *pCmdText  
    )  
{  
    METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)  
        return OLECMDERR_E_NOTSUPPORTED;  
}  

实现CMyControlSite后需要应用到CDHtmlDialog上,重写CreateControlSite虚函数既可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
virtual BOOL CreateControlSite(COleControlContainer* pContainer,
        COleControlSite** ppSite, UINT  nID , REFCLSID  clsid )
{
        if(ppSite == NULL)
    {
        ASSERT(FALSE);
        return FALSE;
    }
 
    CMyControlSite *pBrowserSite =
        new CMyControlSite (pContainer, this);
    if (!pBrowserSite)
        return FALSE;
 
    *ppSite = pBrowserSite;
    return TRUE;
}

现在就可以去编译测试了。到目前还有一个问题没有考虑,如果这段代码整合到现有的CDHtmlDialog应用中而现有的代码使用了其它默认的设定比如说自定义WebBrowser的右健菜单或使用了GetIDispatch函数等情况下原有的代码就不能正常工作了。这部分功能是在MFC的CBrowserControlSite类中处理的,所以CMyControlSite应该把CBrowserControlSite的功能也实现一遍以使CDHtmlDialog的原有封装性不被破坏。在CMyControlSite中实现IDocHostUIHandler接口既可完成此功能。代码声明如下

1
public:
1
CMyControlSite(COleControlContainer *pCnt, CDHtmlDialog *pHandler):COleControlSite(pCnt),m_pHandler(pHandler) {}
1
protected:
1
CDHtmlDialog *m_pHandler;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
BEGIN_INTERFACE_PART(DocHostUIHandler, IDocHostUIHandler)
        STDMETHOD(ShowContextMenu)(DWORD, LPPOINT, LPUNKNOWN, LPDISPATCH);
        STDMETHOD(GetHostInfo)(DOCHOSTUIINFO*);
        STDMETHOD(ShowUI)(DWORD, LPOLEINPLACEACTIVEOBJECT,
            LPOLECOMMANDTARGET, LPOLEINPLACEFRAME, LPOLEINPLACEUIWINDOW);
        STDMETHOD(HideUI)(void);
        STDMETHOD(UpdateUI)(void);
        STDMETHOD(EnableModeless)(BOOL);
        STDMETHOD(OnDocWindowActivate)(BOOL);
        STDMETHOD(OnFrameWindowActivate)(BOOL);
        STDMETHOD(ResizeBorder)(LPCRECT, LPOLEINPLACEUIWINDOW, BOOL);
        STDMETHOD(TranslateAccelerator)(LPMSG, const GUID*, DWORD);
        STDMETHOD(GetOptionKeyPath)(OLECHAR **, DWORD);
        STDMETHOD(GetDropTarget)(LPDROPTARGET, LPDROPTARGET*);
        STDMETHOD(GetExternal)(LPDISPATCH*);
        STDMETHOD(TranslateUrl)(DWORD, OLECHAR*, OLECHAR **);
        STDMETHOD(FilterDataObject)(LPDATAOBJECT , LPDATAOBJECT*);
    END_INTERFACE_PART(DocHostUIHandler)

以下是实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
BEGIN_INTERFACE_MAP(CMyControlSite, COleControlSite) 
    INTERFACE_PART(CMyControlSite, IID_IDocHostUIHandler, DocHostUIHandler)
    INTERFACE_PART(CMyControlSite, IID_IOleCommandTarget, OleCommandTarget)
END_INTERFACE_MAP() 
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::GetExternal(LPDISPATCH *lppDispatch)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->GetExternal(lppDispatch);
}
 
 
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::ShowContextMenu(
    DWORD dwID, LPPOINT ppt, LPUNKNOWN pcmdTarget, LPDISPATCH pdispReserved)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->ShowContextMenu(dwID, ppt, pcmdTarget, pdispReserved);
}
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::GetHostInfo(
    DOCHOSTUIINFO *pInfo)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->GetHostInfo(pInfo);
}
 
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::ShowUI(
    DWORD dwID, LPOLEINPLACEACTIVEOBJECT pActiveObject,
    LPOLECOMMANDTARGET pCommandTarget, LPOLEINPLACEFRAME pFrame,
    LPOLEINPLACEUIWINDOW pDoc)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->ShowUI(dwID, pActiveObject, pCommandTarget, pFrame, pDoc);
}
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::HideUI(void)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->HideUI();
}
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::UpdateUI(void)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->UpdateUI();
}
 
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::EnableModeless(BOOL fEnable)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->EnableModeless(fEnable);
}
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::OnDocWindowActivate(BOOL fActivate)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->OnDocWindowActivate(fActivate);
}
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::OnFrameWindowActivate(
    BOOL fActivate)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->OnFrameWindowActivate(fActivate);
}
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::ResizeBorder(
    LPCRECT prcBorder, LPOLEINPLACEUIWINDOW pUIWindow, BOOL fFrameWindow)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->ResizeBorder(prcBorder, pUIWindow, fFrameWindow);
}
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::TranslateAccelerator(
    LPMSG lpMsg, const GUID* pguidCmdGroup, DWORD nCmdID)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->TranslateAccelerator(lpMsg, pguidCmdGroup, nCmdID);
}
 
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::GetOptionKeyPath(
    LPOLESTR* pchKey, DWORD dwReserved)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->GetOptionKeyPath(pchKey, dwReserved);
}
 
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::GetDropTarget(
    LPDROPTARGET pDropTarget, LPDROPTARGET* ppDropTarget)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->GetDropTarget(pDropTarget, ppDropTarget);
}
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::TranslateUrl(
    DWORD dwTranslate, OLECHAR* pchURLIn, OLECHAR** ppchURLOut)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->TranslateUrl(dwTranslate, pchURLIn, ppchURLOut);
}
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::FilterDataObject(
    LPDATAOBJECT pDataObject, LPDATAOBJECT* ppDataObject)
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
    return pThis->m_pHandler->FilterDataObject(pDataObject, ppDataObject);
}
 
 
STDMETHODIMP_(ULONG) CMyControlSite::XDocHostUIHandler::AddRef()
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
        return pThis->ExternalAddRef();
}
 
STDMETHODIMP_(ULONG) CMyControlSite::XDocHostUIHandler::Release()
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
        return pThis->ExternalRelease();
}
 
STDMETHODIMP CMyControlSite::XDocHostUIHandler::QueryInterface(
    REFIID iid, LPVOID far* ppvObj)    
{
    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)
        return pThis->ExternalQueryInterface(&iid, ppvObj);
}

STDMETHODIMP宏的定义是HRESULT __stdcall,STDMETHODIMP_宏指定了返回值,这两个宏用在cpp实现文件中,对应用于声明时使用的STDMETHOD和STDMETHOD_。

METHOD_PROLOGUE_EX_宏定义了pThis指针来指向外层类。

以上代码基于VS2008,由于不同版本的VS所带的MFC库版本不尽一致所以需要根本具体的版本来处理,目前已知的不同部分主要集中在CreateControlSite上。

CDHtmlDialog探索----WebBrowser扩展和网页Javascript错误处理的更多相关文章

  1. CDHtmlDialog探索----Javascript与窗体交互

    CDHtmlDialog提供了C++与网页的双向交互,通此一系统简单的宏调用可以把网页中各元素的事件直接映射到C++程序中,而在网页中调用C++功能代码就显的不那么直观了.归根结底交互的基理就是实现相 ...

  2. 【转】Javascript错误处理——try…catch

    无论我们编程多么精通,脚本错误怎是难免.可能是我们的错误造成,或异常输入,错误的服务器端响应以及无数个其他原因. 通常,当发送错误时脚本会立刻停止,打印至控制台. 但try...catch语法结构可以 ...

  3. JavaScript错误/异常处理

    JavaScript Try...Catch 语句 介绍:JavaScript中的try...carch语句的作用和C#中的try...catch语句的作用一样, 都是捕获并处理异常. 语法: try ...

  4. 使用 Google Analytics 跟踪 JavaScript 错误

    Google Analytics(谷歌分析)不仅仅是一个流量统计工具,你还可以用它来测量广告活动的有效性,跟踪用户多远到所需的页面流(从点击广告到购物车到结账页面)获取,并基于用户的信息设置浏览器和语 ...

  5. javascript错误处理与调试(转)

    JavaScript 在错误处理调试上一直是它的软肋,如果脚本出错,给出的提示经常也让人摸不着头脑. ECMAScript 第 3 版为了解决这个问题引入了 try...catch 和 throw 语 ...

  6. 第一百二十三节,JavaScript错误处理与调试

    JavaScript错误处理与调试 学习要点: 1.浏览器错误报告 2.错误处理 3.错误事件 4.错误处理策略 5.调试技术 6.调试工具 JavaScript在错误处理调试上一直是它的软肋,如果脚 ...

  7. Visual Studio 2013中因SignalR的Browser Link引起的Javascript错误一则

    众所周知Visual Studio 2013中有一个由SignalR机制实现的Browser Link功能,意思是开发人员可以同时使用多个浏览器进行调试,当按下IDE中的Browser Link按钮后 ...

  8. Java抓取网页数据(原网页+Javascript返回数据)

    有时候由于种种原因,我们需要采集某个网站的数据,但由于不同网站对数据的显示方式略有不同! 本文就用Java给大家演示如何抓取网站的数据:(1)抓取原网页数据:(2)抓取网页Javascript返回的数 ...

  9. JavaScript错误处理

    JavaScript 错误 - Throw.Try 和 Catch JavaScript 测试和捕捉 try 语句允许我们定义在执行时进行错误测试的代码块. catch 语句允许我们定义当 try 代 ...

随机推荐

  1. Java Web之Http协议

    为什么会出现HTTP协议?有什么用? 浏览器和服务器之间进行数据的沟通的时候,需要标准,浏览器有Chrome浏览器,火狐浏览器,IE浏览器等.服务器有Tomcat服务器,IIS服务器等,由于各自标准不 ...

  2. Java使用POI导入Excel异常Cannot get a text value from a numeric cell 解决

    异常原因:Excel数据Cell有不同的类型,当我们试图从一个数字类型的Cell读取出一个字符串并写入数据库时,就会出现Cannot get a text value from a numeric c ...

  3. 设计模式---数据结构模式之组合模式(Composite)

    前提:数据结构模式 常常有一些组建在内部具有特定的数据结构,如果让客户程序依赖这些特定的数据结构,将极大的破坏组件的复用.这时候,将这些数据结构封装在内部,在外部提供统一的接口,来实现与特定数据结构无 ...

  4. Linux记录-GC分析

    查看gc情况: jstat -gc PID 刷新频率 jstat -gc 12538 5000 导出堆内存dump 文件: jmap -dump:file=文件名.bin [pid] 导出线程dump ...

  5. shop++之language

    shop++商城改造此次感悟最深的就是封装.有些东西要整明白就得花点时间. 代码中经常用到这种,我照葫芦画瓢竟然没有用. 天啦,竟然是自己没有定义,还以为是什么高级自动的玩意呢? 文件结构如下: 后面 ...

  6. 学习总结:CSS(二)块级与行级元素特性、盒模型、层模型、BUG与BFC、浮动模型

    一.元素的块级与行级特性 在CSS属性display控制元素是否及如何显示的特性,常用的值有none.inline.block.inline-block,在CSS3中还有一些新的特性状态,在这里不做讨 ...

  7. 【1】【leetcode-77】 组合

    (典型,做过似曾相识但不熟悉,基本知道怎么做但调试了一个多小时各种错) 给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合. 示例: 输入: n = 4, k = 2 输出: ...

  8. SQL Server进阶(十)事务和并发处理

    1 https://www.cnblogs.com/edisonchou/p/6129717.html

  9. Bootstrap 使用

    bootstrap模板为使IE6.7.8版本(IE9以下版本)浏览器兼容html5新增的标签,引入下面代码文件即可. <script src="https://oss.maxcdn.c ...

  10. luogu P4363 [九省联考2018]一双木棋chess

    传送门 对抗搜索都不会,我真是菜死了qwq 首先根据题目条件,可以发现从上到下每一行的棋子数是单调不增的,然后n m都比较小,如果把状态搜出来,可以发现合法状态并不多,所以可以用一个11进制数表示状态 ...