別のスレッドでファイルをダウンロードするフローティングダイアログ

概要

このチュートリアルでは、次のようにダイアログを構築します。

  1. 入力/出力ボックスと2つのボタンを備えたフローティングダイアログ。
  2. ユーザがURLを入力した後、ダウンロードするファイルを指定し、Origin別のスレッドでファイルをダウンロードし、Originを使用して他のことを実行できるようにします。
  3. ダイアログはダウンロードステータスを更新します。
  4. ユーザはダウンロードスレッドを中止できます。

必要なOriginのバージョン: Origin 2024b以降

ダイアログ用HTMLページの作成

  1. コードビルダを開き、新しいHTMLファイルを作成してDownloadFile.htmlという名前でDownload Exampleフォルダに保存します。
  2. 次のコードをコピーし、DownloadFile.html内に貼り付けます。
    <!doctype html>
    <html>
            <head>
                    <meta charset="utf-8" />
                    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
            </head>
            <body>
                    <input id="path" style="width:350px" placeholder="input file url and click Download" onchange="On_Path()"></input>           
                    <br>
                    <input type="button" id="btnDownload" value="Download" onclick="Invoke_Download()"/>            
                    <input type="button" id="btnAbort" value="Abort" onclick="Invoke_Abort()"/>     
                    <br>
                    <input id="hint" style="width:350px;border:none" disabled="true"></div>
            </body>
            <script>
                    function On_Path() {
                            document.getElementById('btnDownload').disabled = false;
                            document.getElementById('hint').value = "";
                    }
                    function Invoke_Download() {
                            var Result = window.external.ExtCall("DownloadOnlineFile", document.getElementById('path').value);
                            document.getElementById('hint').value = Result;
                            document.getElementById('btnDownload').disabled = true;
                    }             
                    function Invoke_Abort() {
                            window.external.ExtCall("DownloadAbort");
                            document.getElementById('btnDownload').disabled = false;
                    }
                    function Update(str) { document.getElementById('hint').value = str; }
            </script>    
    </html>
    
    Note: このコードは、作成したHTMLページに機能を追加します。
    • On_Path():ダウンロードボタンを有効にし、ユーザ入力のファイルURLの後にメッセージを出力
    • Invoke_Download():ユーザがダウンロードボタンを押したイベントに応答
    • Invoke_Abort():ユーザが中止ボタンを押したイベントに応答
    • Update():ダウンロードメッセージの出力

この手順が完了したら、WebブラウザでDownloadFile.htmlを開くと、HTMLページが表示されます。

関数 Invoke_DownloadInvoke_Abortwindow.external.ExtCall はOrigin Cを呼び出すために使用されます。window.external.ExtCallの詳細については、こちらを参照してください。

フローティングHTMLダイアログの作成

これで、Origin Cコードを編集してHTMLダイアログを作成する準備が整いました。

  1. コードビルダで、DownloadDlg.cppという名前の新しいcppファイルをDownload Exampleフォルダに作成します。
  2. 必要なヘッダを含めます。
    #include <Origin.h>
    #include <../OriginLab/DialogEx.h>
    #include <../OriginLab/HTMLDlg.h>
    
  3. HTMLダイアログクラスDownloadDialogを宣言し、DownloadDialogのポインタを定義します。このポインタは、HTMLダイアログをフローティングにするためのものです。
    class DownloadDialog;
    static DownloadDialog* s_pDLDlg;
    
  4. HTMLDlgクラスからDownloadDialogクラスを派生し、メソッドGetInitURL()内のHTMLページをポイントします。
    class DownloadDialog: public HTMLDlg
    {
    protected:
            string GetInitURL(){return GetFilePath(__FILE__) + "DownloadFile.html";}
            string GetDialogTitle(){return "";}
            BOOL GetDlgInitSize(int& width, int& height){ width = 400; height = 150; return true; }
    };
    
  5. モードレスダイアログボックスを呼び出すCreate関数を追加します。
    public:
            int Create()
            {
                    InitMsgMap();
                    int nRet = Create(NULL, 0);
                    Visible = true;
                    return nRet;
            }
    
  6. クラスDownloadDialog内のダイアログメッセージをマップして、処理するイベントと処理する関数を指定します。イベントに応答するイベントハンドラメソッドを追加します。
    protected:
    EVENTS_BEGIN_DERIV(HTMLDlg)
            ON_DESTROY(OnDestroy)
            ON_IDLE(OnIdle)
    EVENTS_END_DERIV
            BOOL OnDestroy()
            {
                    BOOL bRet = HTMLDlg::OnDestroy();
                    
                    delete this;
                    s_pDLDlg = NULL;
                    return bRet;
            }
            BOOL OnIdle()
            {
                    string strMsg, strJS;
                    double err;
                    LT_get_var("@OCDL", &err); 
                    if( err < 0 ) 
                    {
                            if( !m_strFile.IsEmpty() )
                            {
                                    switch(err)
                                    {
                                    case OHTTP_E_INVALID_URL:
                                            strMsg = "Invalid URL"; 
                                            break;
                                    case OHTTP_E_USER_CANCEL: 
                                            strMsg = "Abort";
                                            break;
                                    default:
                                            strMsg.Format("err = %g", err);
                                    }
                                    m_strFile.Empty();
                            }
                    }
                    else if( err == 0 ) 
                    {
                            if( m_strFile.IsFile() )
                            {
                                    strMsg.Format("download complete: %s", m_strFile);
                                    m_strFile.Empty();
                            }                     
                    }
                    else
                            strMsg.Format("downloading %.2f%%", err);
                    
                    
                    if( !strMsg.IsEmpty() )
                    {
                            strJS.Format("Update(\'%s\')", strMsg);//call Update() in html code                   
                            CallJavaScript(strJS);
                    }
                    return TRUE;
            }
    
    Note: Originがアイドル状態のときにOnIdle()がトリガーされ、ダウンロードステータスを取得し、DHtmlControlクラスのメンバ関数CallJavaScript()によってJavaScriptUpdate()を呼び出します。

Origin CにJavaScript呼び出し可能なプロトタイプの追加

このセクションでは、ダイアログクラスDownloadDialog内でメソッドを追加します。

  • DownloadOnlineFile()はユーザがDownloadキーを押したときにファイルをダウンロードするために、JavaScript関数Invoke_Download()で呼び出されます。
  • DownloadAbort()は、ユーザがAbortキーを押したときにダウンロードスレッドを中止するためにJavaScript関数Invoke_Abort()で呼び出されます。
  1. ダイアログクラス内にメソッドと DECLARE_DISPATCH_MAP を追加します。
    public:      
            DECLARE_DISPATCH_MAP
            string DownloadOnlineFile(string strURL) 
            {
                    string strMsg, strName = GetFileName(strURL);
                    m_strFile = GetOriginPath(ORIGIN_PATH_USER) + strName;
                    BOOL bWait = FALSE, bShowMsg = TRUE; // ファイルを別のスレッドでダウンロードするとダウンロード完了後にメッセージログにメッセージが表示
                    double err;
                    if( okutil_http_download(strURL, m_strFile, 0, 0, FALSE, bWait, bShowMsg) )
                    {
                            LT_get_var("@OCDL", &err); 
                            strMsg.Format("previous download not completed %.2f%%", err);
                    }
                    else
                            strMsg = "downloading...";
                    return strMsg;
            }     
            void DownloadAbort(){ LT_set_var("@OCDL", 2); }
    private:
            string m_strFile;
    
  2. OriginCダイアログクラスのメソッドをこのHTMLダイアログにマッピングします。
    BEGIN_DISPATCH_MAP(DownloadDialog, HTMLDlg)
        DISP_FUNCTION(DownloadDialog, DownloadOnlineFile, VTS_STR, VTS_STR)
        DISP_FUNCTION(DownloadDialog, DownloadAbort, VTS_VOID, VTS_VOID)
    END_DISPATCH_MAP
    
    Note:
    • DISP_FUNCTIONの詳細はこちらをご覧ください。
    • okutil_http_download()の詳細はこちらを参照してください。
    • システム変数 @OCDL はダウンロードステータスを返し、@OCDL> 1はダウンロードスレッドを中止します。

ダイアログの起動

これで、ダイアログを起動する準備ができました。

  1. メイン機能の追加
    int DownloadDlg(int nMsg, DWORD dwCntrl = 0, LPVOID lpData = NULL)
    {
            bool bClose = OMSG_CLOSE==nMsg? true:false;
            if(bClose)
            {
                    if(s_pDLDlg)
                    {
                            Window winDlg = s_pDLDlg->GetWindow();
                            if(winDlg)
                                    winDlg.SendMessage(WM_CLOSE);
                            delete s_pDLDlg;
                            s_pDLDlg = NULL;
                    }
                    return 0;
            }
            
            if(!s_pDLDlg)
            {
                    s_pDLDlg = new DownloadDialog();
                    s_pDLDlg->Create();
            }
            return 0;
    }
    
    void open_downloaddlg(){DownloadDlg(OMSG_OPEN);}
    
  2. すべてのコードを保存してビルドします。
  3. open_downloaddlg を実行してダイアログを表示します。