当前位置:   article > 正文

通过nsis和duilib实现自定义安装界面_nsis duilib

nsis duilib
 nsis用于实现安装逻辑,duilib用于实现UI界面
  • 1

通过nsis调用duilib生成的dll库来实现。现截取部分duilib代码用于展示如何使用duilib编写代码。
cpp文件如下:

#include <windows.h>
#include <commctrl.h>
#include <Shlobj.h>
#include "plugin-common.h"
#include "DlgMain.h"

#pragma comment(lib,"Shell32.lib")

HINSTANCE g_hInstance;
HWND g_hwndParent;
extra_parameters *g_pluginParms = NULL;
CDlgMain *g_pMainDlg = NULL;
std::map<HWND, WNDPROC> g_windowInfoMap;
CDuiString g_progressCtrlName = _T("");
CDuiString g_tabLayoutCtrlName = _T("");
bool g_bMSGLoopFlag = true;



#define NSMETHOD_INIT(parent) {\
        g_pluginParms = extra; \
        g_hwndParent = parent; \
        EXDLL_INIT(); }

BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
    g_hInstance = (HINSTANCE)hInst;

    if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
        //do what you want at init time.
    }

    if (ul_reason_for_call == DLL_THREAD_DETACH || ul_reason_for_call == DLL_PROCESS_DETACH) {
        //clean up code.
    }

    return TRUE;
}

// NSIS插件导出函数,NSIS规定函数声明格式如下:
extern "C" __declspec(dllexport) void __cdecl

/*
* 在nsis脚本中调用方法myPlugin::myFunction /NOUNLOAD $2
*  /NOUNLOAD 表示调用完此方法后不卸载这个dll,用于保存dll的数据
* hwndParent:安装窗口的句柄
* stacktop:nsis传入的参数堆栈, 通过popint/popstring 可以取出来
* extra:插件里面调用script的函数就需要用到这个
*/
add(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        // == 添加自己代码
        int i = popint();
        int j = popint();
        int k = i + j;
        pushint(k);
        // ==
    }
}
//窗口大小
extern "C" __declspec(dllexport) void __cdecl
GetDialogSize(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        HWND hwnd = (HWND)popint();
        RECT rect;
        ::GetWindowRect(hwnd, &rect);

        pushint(rect.bottom - rect.top);
        pushint(rect.right - rect.left);
    }
}
//窗口风格
extern "C" __declspec(dllexport) void __cdecl
GetDialogStyle(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        HWND hwnd = (HWND)popint();
        int style = (int)::GetWindowLongA(hwnd, GWL_STYLE);
        pushint(style);
    }
}

extern "C" __declspec(dllexport) void __cdecl
GetSetupPath(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        char buf[512] = { 0 };
        ::GetModuleFileName(NULL, buf, 512);
        pushstring(buf);
    }
}

extern "C" __declspec(dllexport) void __cdecl
Trace(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        char buf[1024] = { 0 };
        popstring(buf);
        DUI__Trace(_T("NSISHelper Trace:%s"), buf);
    }
}

extern "C" __declspec(dllexport) void __cdecl
GetCtrlPos(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        HWND hwnd = (HWND)popint();
        RECT rect;
        GetClientRect(hwnd, &rect);
        DUI__Trace(_T("%d %d %d %d %d"), hwnd, rect.left, rect.top, rect.right, rect.bottom);

        POINT lt = { rect.left, rect.top };
        POINT rb = { rect.right, rect.bottom };

        ::ClientToScreen(hwndParent, &lt);
        ::ClientToScreen(hwndParent, &rb);

        pushint(rb.y);
        pushint(rb.x);
        pushint(lt.y);
        pushint(lt.x);
    }
}


 //=========================================== DUILIB =============================================
//许可协议界面
NSISAPI FindControl(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    char controlName[MAX_PATH];
    ZeroMemory(controlName, MAX_PATH);

    popstring(controlName);
    CControlUI *pControl = static_cast<CControlUI *>(g_pMainDlg->GetPaintManagerUI()->FindControl(controlName));

    if (pControl == NULL)
        pushint(-1);

    pushint(0);
}

//绑定控件
NSISAPI  OnControlBindNSISScript(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    char controlName[MAX_PATH];
    ZeroMemory(controlName, MAX_PATH);

    popstring(controlName);
    int callbackID = popint();
    g_pMainDlg->SaveToControlCallbackMap(controlName, callbackID);//放入所有控件
}

NSISAPI ExitDUISetup(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    ExitProcess(0);
}


static UINT_PTR PluginCallback(enum NSPIM msg)
{
    return 0;
}

//初始化界面--欢迎界面
NSISAPI InitDUISetup(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    extra->RegisterPluginCallback(g_hInstance, PluginCallback);
    {
        CPaintManagerUI::SetInstance(g_hInstance);
        char buf[512] = { 0 };
        ::GetModuleFileName(NULL, buf, 512);
        int len = strlen(buf);
        --len;

        while (len >= 0) {
            if (buf[len] == '\\')
                break;

            buf[len] = '\0';
            --len;
        }

        sprintf_s(buf, "%sskin", buf);

        //CPaintManagerUI::SetResourcePath(buf);
        g_pMainDlg = new CDlgMain();
        g_pMainDlg->Create(NULL, _T("标题名字"), UI_WNDSTYLE_FRAME, WS_EX_STATICEDGE | WS_EX_APPWINDOW, 0, 0, 588, 384);
        g_pMainDlg->CenterWindow();
        g_pMainDlg->ShowWindow(FALSE);
        pushint(int(g_pMainDlg->GetHWND()));

    }
}

//显示页面
NSISAPI ShowPage(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        g_pMainDlg->ShowWindow(true);
        //CPaintManagerUI::MessageLoop();
        MSG msg = { 0 };
        while (::GetMessage(&msg, NULL, 0, 0) && g_bMSGLoopFlag)
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }
    }
}

//设置编辑框内容
NSISAPI SetEdit(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        char buf[512] = { 0 };
        popstring(buf);
        CEditUI *pEdit = static_cast<CEditUI *>(g_pMainDlg->GetPaintManagerUI()->FindControl("btEdit"));
        if (pEdit)
            pEdit->SetText(buf);
    }
}

//checkBox选型
NSISAPI GetCheckboxStatus(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        char pszName[512] = { 0 };

        popstring(pszName);//从nsis获取控件
        CCheckBoxUI *pChbAgree = static_cast<CCheckBoxUI *>(g_pMainDlg->GetPaintManagerUI()->FindControl(pszName));
        if (!pChbAgree) {
            pushint(-1);
            return;
        }
        DUI__Trace("%s status:%d", pszName, pChbAgree->GetCheck() ? 1 : 0);
        pushint(pChbAgree->GetCheck() ? 1 : 0);//输出给nsis。
    }
}

//设置进度
NSISAPI SetSliderRange(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        char buf[512] = { 0 };

        //从nsis接收多个参数
        popstring(buf);
        int iMin = popint();
        int iMax = popint();

        CProgressUI *pProgress = static_cast<CProgressUI *>(g_pMainDlg->GetPaintManagerUI()->FindControl(buf));


        if (pProgress == NULL)
            return;
        //设置进度
        pProgress->SetMaxValue(iMax);
        pProgress->SetMinValue(iMin);
    }
}

//设置进度值
NSISAPI SetSliderValue(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        char buf[512] = { 0 };
        popstring(buf);
        int iValue = popint();

        CProgressUI *pProgress = static_cast<CProgressUI *>(g_pMainDlg->GetPaintManagerUI()->FindControl(buf));

        if (pProgress)
            pProgress->SetValue(iValue);
    }
}

//文件路径
NSISAPI SetDirValue(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        char buf[512] = { 0 };
        popstring(buf);
        CEditUI *pEdit = static_cast<CEditUI *>(g_pMainDlg->GetPaintManagerUI()->FindControl("editDir"));
        if (pEdit)
            pEdit->SetText(buf);
    }
}

NSISAPI GetDirValue(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        CDuiString strFolderPath;
        CEditUI *pEdit = static_cast<CEditUI *>(g_pMainDlg->GetPaintManagerUI()->FindControl("editDir"));
        if (pEdit)
            strFolderPath = pEdit->GetText();

        pushstring((char*)strFolderPath.GetData());
    }
}

//选择安装路径--点击更改弹出文件路径选择对话框
NSISAPI SelectInstallDir(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        //BROWSEINFO SHGetPathFromIDList 弹出文件夹选择框
        BROWSEINFO bi;
        memset(&bi, 0, sizeof(BROWSEINFO));

        bi.hwndOwner = g_pMainDlg->GetHWND();
        bi.lpszTitle = "选择安装路径";
        bi.ulFlags = 0x0040;

        char szFolderPath[MAX_PATH] = { 0 };
        LPITEMIDLIST idl = SHBrowseForFolder(&bi);
        if (idl == NULL)
        {
            pushstring(szFolderPath);
            return;
        }

        SHGetPathFromIDList(idl, szFolderPath);

        CEditUI *pEdit = static_cast<CEditUI *>(g_pMainDlg->GetPaintManagerUI()->FindControl("editDir"));
        if (pEdit)
            pEdit->SetText(szFolderPath);

        pushstring(szFolderPath);
    }
}

//更新
NSISAPI StartInstall ( HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
    NSMETHOD_INIT(hwndParent);
    {
        g_bMSGLoopFlag = false;
    }
}

BOOL CALLBACK PluginNewWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    BOOL res = 0;
    std::map<HWND, WNDPROC>::iterator iter = g_windowInfoMap.find( hwnd );

    if( iter != g_windowInfoMap.end() ) {
        if (message == WM_NCCREATE || message == WM_CREATE || message == WM_PAINT || message== WM_NCPAINT) {
            ShowWindow( hwnd, SW_HIDE );
        } else if( message == LVM_SETITEMTEXT ) {
            ;
        } else if( message == PBM_SETPOS ) {
            CProgressUI *pProgress = static_cast<CProgressUI *>(g_pMainDlg->GetPaintManagerUI()->FindControl( g_progressCtrlName ));

            if( pProgress == NULL )
                return 0;

            pProgress->SetMaxValue( 30000 );
            pProgress->SetValue( (int)wParam);

            if( pProgress->GetValue() == 30000 ) {
                CTabLayoutUI *pTab = static_cast<CTabLayoutUI *>(g_pMainDlg->GetPaintManagerUI()->FindControl( g_tabLayoutCtrlName ));
                if( pTab == NULL )
                    return -1;

                int currentIndex = pTab->GetCurSel();
                DUI__Trace("tabName:%s index:%d",g_tabLayoutCtrlName,currentIndex);
                pTab->SelectItem(2);

            }
        } else {
            res = CallWindowProc( iter->second, hwnd, message, wParam, lParam);
        }
    }

    return res;
}
  • 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
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392

如下代码用于控制控件的响应文件:

#include "DlgMain.h"


CDlgMain::CDlgMain()
{
}

CDlgMain::~CDlgMain()
{

}

void CDlgMain::Notify( TNotifyUI& msg )
{
    std::map<CDuiString, int >::iterator iter = m_controlCallbackMap.find( msg.pSender->GetName() );
    if( _tcsicmp( msg.sType, _T("click") ) == 0 ){
        if( iter != m_controlCallbackMap.end() )
            g_pluginParms->ExecuteCodeSegment( iter->second - 1, 0 );
    }
    else if( _tcsicmp( msg.sType, _T("textchanged") ) == 0 ){
        if( iter != m_controlCallbackMap.end() )
            g_pluginParms->ExecuteCodeSegment( iter->second - 1, 0 );
    } else {
        WindowImplBase::Notify(msg);
    }
}

LRESULT CDlgMain::HandleCustomMessage( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
    return 0;
}

void CDlgMain::InitWindow()
{
    CRichEditUI * pRichEdit = static_cast<CRichEditUI*>(m_PaintManager.FindControl(_T("editLicense")));
    if(pRichEdit) {
        HRSRC hRsrc = FindResourceA(CPaintManagerUI::GetInstance(), MAKEINTRESOURCEA(IDR_TEXT_LICENSE), "TEXT");
        if(!hRsrc)
            return;

        DWORD dwSize = SizeofResource(CPaintManagerUI::GetInstance(), hRsrc);
        if(dwSize==0)
            return;

        HGLOBAL hGlobal = LoadResource(CPaintManagerUI::GetInstance(), hRsrc);
        if(!hGlobal)
            return;

        LPVOID lpBuffer = LockResource(hGlobal);
        if(!lpBuffer)
            return;

        pRichEdit->AppendText((char*)lpBuffer);

        FreeResource(hGlobal);
    }
}
  • 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

可以看出,所有控件都通过绑定函数放到了集合中,在notify中找到控件来响应动作。
通过pop来接收nsis参进来的参数,push来给nsis传递参数。

在nsis中调用语法如下所示
这是绑定安装界面控件事件格式

    nsDui::FindControl "btnSelectDir"
    Pop $0
    ${If} $0 == 0
        GetFunctionAddress $0 OnBtnSelectDir
        nsDui::OnControlBindNSISScript "btnSelectDir" $0
    ${EndIf}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在安装逻辑中使用格式如下

Function OnBtnSelectDir
    nsDui::SelectInstallDir
    Pop $0
FunctionEnd
  • 1
  • 2
  • 3
  • 4

参考wyrover的代码,感谢,获取源码请点击此链接

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/112596
推荐阅读
相关标签
  

闽ICP备14008679号