Frost Moon Project

Src/Function.cpp-Ashley Ver.1.30- - Frost Moon Project アクセスランキング

Home > ソフトウェア > Ashley > Ashley130.zip/Ashley130.exe > Src > Function.cpp

//Function.cpp
//様々な便利関数

/*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
    Ashley Ver.1.30
    Coded by x@rgs

    This code is released under NYSL Version 0.9982
    See NYSL_withfaq.TXT for further details.

    Ashleyは、アップローダからダウンロードしたZIPやRAR等のファイル名を元に戻すソフトです。
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*/


#include"Pch.h"
#include"Function.h"
#include"Path.h"
#include"resources/resource.h"
#include<objidl.h>
#include<shlobj.h>
#include<shlwapi.h>
#include<wininet.h>

//SHBrowseForFolder()
#ifndef BIF_NONEWFOLDERBUTTON
    #define BIF_NONEWFOLDERBUTTON   0x00000200
#endif

//SHAutoComplete()
#ifndef SHACF_DEFAULT
    #define SHACF_DEFAULT                   0x00000000
    #define SHACF_FILESYSTEM                0x00000001
    #define SHACF_URLALL                    (SHACF_URLHISTORY|SHACF_URLMRU)
    #define SHACF_URLHISTORY                0x00000002
    #define SHACF_URLMRU                    0x00000004
    #define SHACF_USETAB                    0x00000008
    #define SHACF_FILESYS_ONLY              0x00000010
    #define SHACF_AUTOSUGGEST_FORCE_ON      0x10000000
    #define SHACF_AUTOSUGGEST_FORCE_OFF     0x20000000
    #define SHACF_AUTOAPPEND_FORCE_ON       0x40000000
    #define SHACF_AUTOAPPEND_FORCE_OFF      0x80000000
#endif


//Function.hで宣言された以外の関数
//SHBrowseForFolder()のコールバック
int CALLBACK BrowseForFolderCallbackProc(HWND hWnd,UINT uMsg,LPARAM lParam,LPARAM lpData);
//ファイル保存ダイアログ
bool SaveFileDialog(HWND hWnd,TCHAR* pszResult,int iLength,const TCHAR* pszFilter,const TCHAR* pszTitle);
//ファイルに一行書き込む
bool WriteFileLine(HANDLE hFile,LPSTR lpszLine,bool bUTF8);
//バージョンファイルを元に最新版かどうか比較
int CheckLatestVersion(TCHAR* pszApplicationName,TCHAR* pszVersionFilePath,TCHAR* pszResultFileName,TCHAR* pszResultUrl);
//ファイルをダウンロード
bool DownloadFile(TCHAR* pszServer,TCHAR* pszFileName,TCHAR* pszUrl,HWND hStatusBar=NULL,HWND hStatusProgressBar=NULL);


//一つのファイルを選択
bool OpenSingleFileDialog(HWND hWnd,TCHAR* pszResult,int iLength,const TCHAR* pszFilter,const TCHAR* pszTitle){
    TCHAR szDlgErr[30]={0};//CommDlgExtendedError()用

    pszResult[0]=_T('\0');
    OPENFILENAME ofnOpen;
    ZeroMemory(&ofnOpen,sizeof(OPENFILENAME));
    ofnOpen.lStructSize=sizeof(OPENFILENAME);
    ofnOpen.hwndOwner=hWnd;
    ofnOpen.lpstrFilter=pszFilter;
    ofnOpen.lpstrFile=pszResult;
    ofnOpen.nMaxFile=iLength;
    ofnOpen.lpstrTitle=pszTitle;
    ofnOpen.Flags=OFN_EXPLORER|OFN_HIDEREADONLY|OFN_FILEMUSTEXIST;
    if(GetOpenFileName(&ofnOpen)){
        if(path::IsDirectory(pszResult)){
            pszResult[0]=_T('\0');
            return false;
        }
    }else{
        DWORD dwDlgErr=CommDlgExtendedError();
        if(dwDlgErr!=0){
            wsprintf(szDlgErr,_T("ファイルの選択に失敗しました。\nErrCode:0x%08X"),dwDlgErr);
            MessageBox(hWnd,szDlgErr,NULL,MB_ICONWARNING);
            pszResult[0]=_T('\0');
        }
        return false;
    }
    return true;
}

//ファイル保存ダイアログ
bool SaveFileDialog(HWND hWnd,TCHAR* pszResult,int iLength,const TCHAR* pszFilter,const TCHAR* pszTitle){
    TCHAR szDlgErr[30]={0};//CommDlgExtendedError()用

//    pszResult[0]=_T('\0');<-デフォルトファイル名を有効にするためコメントアウト
    OPENFILENAME ofnSave;
    ZeroMemory(&ofnSave,sizeof(OPENFILENAME));
    ofnSave.lStructSize=sizeof(OPENFILENAME);
    ofnSave.hwndOwner=hWnd;
    ofnSave.lpstrFilter=pszFilter;
    ofnSave.lpstrFile=pszResult;
    ofnSave.nMaxFile=iLength;
    ofnSave.lpstrTitle=pszTitle;
    ofnSave.Flags=OFN_EXPLORER|OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_OVERWRITEPROMPT;
    if(GetSaveFileName(&ofnSave)==0){
        DWORD dwDlgErr=CommDlgExtendedError();
        if(dwDlgErr!=0){
            wsprintf(szDlgErr,_T("ファイルの選択に失敗しました。\nErrCode:0x%08X"),dwDlgErr);
            MessageBox(hWnd,szDlgErr,NULL,MB_ICONWARNING);
            pszResult[0]=_T('\0');
        }
        return false;
    }
    return true;
}

int CALLBACK BrowseForFolderCallbackProc(HWND hWnd,UINT uMsg,LPARAM lParam,LPARAM lpData){
    static HWND hEdit;

    switch(uMsg){
        case BFFM_INITIALIZED:{
            if(lpData){
                //初期ディレクトリ設定
                SendMessage(hWnd,BFFM_SETSELECTION,(WPARAM)true,(LPARAM)lpData);
                hEdit=FindWindowEx(hWnd,NULL,_T("Edit"),NULL);

//                SetWindowLongPtr(hWnd,GWL_STYLE,GetWindowLongPtr(hWnd,GWL_STYLE)^WS_THICKFRAME);

                if(hEdit){
                    //エディットコントロールにオートコンプリート機能を実装
                    SHAutoComplete(hEdit,SHACF_FILESYSTEM|SHACF_URLALL|SHACF_FILESYS_ONLY|SHACF_USETAB);
                }
            }
            break;
        }

        case BFFM_SELCHANGED:{
            LPITEMIDLIST lpItemIDList=(LPITEMIDLIST)lParam;
            TCHAR szDirectory[MAX_PATH]={0};

            //TODO:マイコンピュータを素通りしてしまう
            if(SHGetPathFromIDList(lpItemIDList,szDirectory)){
                if(hEdit){
                    path::AddBackSlash(szDirectory,szDirectory);
                    SendMessage(hEdit,WM_SETTEXT,(WPARAM)0,(LPARAM)szDirectory);
                }
            }
            break;
        }

        //無効なディレクトリ名であった場合
        case BFFM_VALIDATEFAILED:return 1;

        default:
            break;
    }
    return 0;
}

//ディレクトリを選択
bool SelectDirectory(HWND hWnd,TCHAR* pResult,const TCHAR* pszTitle,const TCHAR* pszDefaultDirectory){
    bool bResult=false;

    CoInitialize(NULL);
    LPTSTR lpBuffer;
    LPITEMIDLIST pidlRoot;//ルートディレクトリ
    LPITEMIDLIST lpItemIDList=NULL;
    LPMALLOC lpMalloc=NULL;
    if(FAILED(SHGetMalloc(&lpMalloc)))return false;
    if((lpBuffer=(LPTSTR)lpMalloc->Alloc(MAX_PATH))==NULL)return false;
    if(!SUCCEEDED(SHGetSpecialFolderLocation(NULL,CSIDL_DESKTOP/*CSIDL_DRIVES*/,&pidlRoot))){
        lpMalloc->Free(lpBuffer);
        CoUninitialize();
        return false;
    }

    //デスクトップのパスを取得
//    TCHAR szDesktopPath[MAX_PATH]={0};
    SHFILEINFO shFileInfo;

    ZeroMemory(&shFileInfo,sizeof(SHFILEINFO));
    SHGetFileInfo((LPCTSTR)pidlRoot,0,&shFileInfo,sizeof(SHFILEINFO),SHGFI_DISPLAYNAME|SHGFI_PIDL);
//    SHGetSpecialFolderPath(NULL,szDesktopPath,CSIDL_DESKTOP,false);

    BROWSEINFO BrowseInfo;
    ZeroMemory(&BrowseInfo,sizeof(BrowseInfo));
    BrowseInfo.hwndOwner=hWnd;
    BrowseInfo.pidlRoot=pidlRoot;
    BrowseInfo.pszDisplayName=lpBuffer;
    BrowseInfo.lpszTitle=(pszTitle)?pszTitle:_T("フォルダを選択してください");
    //BIF_DONTGOBELOWDOMAINを有効にすると、デスクトップ上のファイルが列挙されてしまう
    BrowseInfo.ulFlags=BIF_USENEWUI|BIF_NONEWFOLDERBUTTON|BIF_RETURNONLYFSDIRS/*|BIF_DONTGOBELOWDOMAIN*/|BIF_VALIDATE;
    BrowseInfo.lpfn=BrowseForFolderCallbackProc;
    BrowseInfo.lParam=reinterpret_cast<LPARAM>((pszDefaultDirectory)?pszDefaultDirectory:shFileInfo.szDisplayName);//szDesktopPath;
    BrowseInfo.iImage=0;

    lpItemIDList=SHBrowseForFolder(&BrowseInfo);
    if(lpItemIDList){
        if(SHGetPathFromIDList(lpItemIDList,pResult)){
            bResult=true;
        }
        lpMalloc->Free(lpItemIDList);
    }
    lpMalloc->Free(pidlRoot);
    lpMalloc->Free(lpBuffer);
    lpMalloc->Release();
    CoUninitialize();
    return bResult;
}

//ファイルの削除
//\0は既に追加済みとする
int MoveToRecycleBin(HWND hWnd,const TCHAR* lpszPath){
    int iResult=0;
    SHFILEOPSTRUCT ShFileOp;

    ZeroMemory(&ShFileOp,sizeof(SHFILEOPSTRUCT));
    ShFileOp.pFrom=lpszPath;
    ShFileOp.hwnd=hWnd;
    ShFileOp.wFunc=FO_DELETE;
    ShFileOp.pTo=NULL;
    ShFileOp.fFlags=FOF_FILESONLY|FOF_ALLOWUNDO|FOF_NOCONFIRMATION|FOF_MULTIDESTFILES;
    ShFileOp.fAnyOperationsAborted=false;
    ShFileOp.hNameMappings=NULL;
    ShFileOp.lpszProgressTitle=NULL;
    iResult=SHFileOperation(&ShFileOp);
    iResult=ShFileOp.fAnyOperationsAborted;//削除をキャンセルした場合true
    return iResult;
}

//ショートカットを作成
//C++ではなく、Cの場合メンバlpVtblを介さなければならない
//又、型REFCLSIDの宣言が異なる為、CoCreateInstance()の引数にも注意
//例えば、C++の場合はCLSID_ShellLink
//Cの場合は&CLSID_ShellLink
bool CreateShortcut(LPCTSTR lpszShortcutFile,LPCTSTR lpszTargetFile,LPCTSTR lpszArgs,LPCTSTR lpszDescription,LPCTSTR lpszWorkingDirectory){
    bool bResult=false;

    //COMの初期化を行う
    CoInitialize(NULL);
    //シェルリンク用インターフェイス
    IShellLink *pShellLink=NULL;
    //ファイル保存用インターフェイス
    IPersistFile *pPersistFile=NULL;

    //IShellLinkのポインタを取得する
    if(SUCCEEDED(CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(LPVOID*)&pShellLink))){
        //IPersistFileのポインタを取得する
        if(SUCCEEDED(pShellLink->QueryInterface(IID_IPersistFile,(LPVOID*)&pPersistFile))){
            //リンクパス
            if(SUCCEEDED(pShellLink->SetPath(lpszTargetFile))){
                //実行時の引数
                if(lpszArgs){
                    pShellLink->SetArguments(lpszArgs);
                }
                //説明文
                if(lpszDescription){
                    pShellLink->SetDescription(lpszDescription);
                }
                //作業ディレクトリ
                if(lpszWorkingDirectory){
                    pShellLink->SetWorkingDirectory(lpszWorkingDirectory);
                }

#ifdef _UNICODE
                //ショートカットファイルの保存
                if(SUCCEEDED(pPersistFile->Save(lpszShortcutFile,true)))bResult=true;
#else
                WCHAR szShortcutFileW[MAX_PATH];
                if(MultiByteToWideChar(CP_ACP,0,lpszShortcutFile,-1,szShortcutFileW,MAX_PATH)>0){
                    //ショートカットファイルの保存
                    if(SUCCEEDED(pPersistFile->Save(szShortcutFileW,true)))bResult=true;
                }
#endif //_UNICODE

            }
            pPersistFile->Release();
        }
        pShellLink->Release();
    }
    //COMを解放
    CoUninitialize();
    return bResult;
}

//ファイルの行数を取得
int GetFileLineCount(const TCHAR* pszFilePath){
    FILE *fp;
    TCHAR szLine[MAX_PATH*2]={0};
    int iCount=0;

    fp=_tfopen(pszFilePath,_T("r"));
    if(fp==NULL){
        return 0;
    }

    while(_fgetts(szLine,ARRAY_SIZEOF(szLine),fp)!=NULL){
        iCount++;
    }

    fclose(fp);
    return iCount;
}

//ファイルの先頭から指定された行まで削除
bool ShiftFile(const TCHAR* pszFilePath,int iLine){
    FILE *fp,*fpTemp;
    TCHAR szLine[MAX_PATH*2]={0};
    TCHAR szTempFilePath[MAX_PATH]={0};
    int iCount=1;
    bool bResult=false;

    //ログファイルを開く
    fp=_tfopen(pszFilePath,_T("r"));
    if(fp==NULL){
        return false;
    }

    //一時ファイル名作成
    wsprintf(szTempFilePath,_T("%s.tmp"),pszFilePath);

    //一時ファイルを開く
    fpTemp=_tfopen(szTempFilePath,_T("w"));

    while(_fgetts(szLine,ARRAY_SIZEOF(szLine),fp)!=NULL){
        if(iCount>iLine){
            //一時ファイルに書き込む
            _fputts(szLine,fpTemp);
        }
        iCount++;
    }

    //ファイルを閉じる
    fclose(fp);
    fclose(fpTemp);

    //元のファイルを削除し、一時ファイルをリネーム
    if(_tremove(pszFilePath)==0){
        if(_trename(szTempFilePath,pszFilePath)==0){
            bResult=true;
        }
    }

    return bResult;
}

//ファイルに一行書き込む
bool WriteFileLine(HANDLE hFile,LPSTR lpszLine,bool bUTF8){
    if(hFile==NULL)return false;

    bool bResult=false;
    const BYTE byUTF8BOM[3]={0xef,0xbb,0xbf};
    const char szCRLF[]="\r\n";
    DWORD dwNumberOfBytesWrite;
    LARGE_INTEGER liFileSize;

    //UTF-8の場合先にBOMを書き込み
    GetFileSizeEx(hFile,&liFileSize);
    if(liFileSize.QuadPart==0&&bUTF8){
        WriteFile(hFile,byUTF8BOM,(DWORD)sizeof(byUTF8BOM),&dwNumberOfBytesWrite,NULL);
        printf("WriteBOM");
    }

    LARGE_INTEGER liDistanceToMove;
    liDistanceToMove.QuadPart=0;

    //ファイルポインタを末尾に移動
    SetFilePointer(hFile,0,NULL,FILE_END);
    if((WriteFile(hFile,lpszLine,lstrlenA(lpszLine),&dwNumberOfBytesWrite,NULL))!=0)bResult=true;
    if((WriteFile(hFile,szCRLF,lstrlenA(szCRLF),&dwNumberOfBytesWrite,NULL))!=0)bResult=true;

    return bResult;
}

//ログファイル出力
bool WriteLog(const TCHAR* pszLogFile,const TCHAR* pszState,const TCHAR* pszOriginal,const TCHAR* pszRenamed,bool bUTF8){
    HANDLE hFile=CreateFile(pszLogFile,GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
    if(hFile==INVALID_HANDLE_VALUE)return false;

    SYSTEMTIME SystemTime;

    GetLocalTime(&SystemTime);

    bool bResult=false;
    char szLogA[MAX_PATH]={0};
    TCHAR szLog[MAX_PATH*2]={0};

    wsprintf(szLog,_T("%04d/%02d/%02d %02d:%02d:%02d,%s,%s,%s"),SystemTime.wYear,SystemTime.wMonth,SystemTime.wDay,
                                                        SystemTime.wHour,SystemTime.wMinute,SystemTime.wSecond,
                                                        pszState,pszOriginal,pszRenamed
    );
    WideCharToMultiByte((bUTF8)?CP_UTF8:CP_ACP,0,szLog,-1,szLogA,MAX_PATH,NULL,NULL);
    bResult=WriteFileLine(hFile,szLogA,bUTF8);
    CloseHandle(hFile);
    return bResult;
}

//ステータスバー上にプログレスバーを作成
HWND CreateProgressBarOnStatusBar(HINSTANCE hInstance,HWND hStatusBar,int iIndex){
    if(hInstance==NULL||hStatusBar==NULL)return NULL;
    RECT rcStatus;//ステータスバーの位置

    SendMessage(hStatusBar,SB_GETRECT,(WPARAM)iIndex,(LPARAM)&rcStatus);//ステータスバーの位置を取得
    //プログレスバー作成
    return CreateWindowEx(0,
                            PROGRESS_CLASS,
                            NULL,
                            WS_CHILD|WS_VISIBLE,
                            rcStatus.left,
                            rcStatus.top,
                            rcStatus.right,
                            rcStatus.bottom,
                            hStatusBar,
                            0,
                            hInstance,
                            NULL
    );
}

//スピン+エディットコントロールの初期設定
bool InitializeSpinEditControl(HWND hSpin,HWND hEdit,int iMinimum,int iMaximum,int iCurrent){
    if(hSpin==NULL||hEdit==NULL)return false;

    //エディットコントロールを関連付ける
    SendMessage(hSpin,UDM_SETBUDDY,(WPARAM)hEdit,(LPARAM)0);
    //最大値と最小値を設定
    SendMessage(hSpin,UDM_SETRANGE32,(WPARAM)iMinimum,(LPARAM)iMaximum);
    //現在サイズの位置に移動
    SendMessage(hSpin,UDM_SETPOS,(WPARAM)0,(LPARAM)MAKELONG((short)iCurrent,0));
    return true;
}

//エディットボックスから数値を取得
int GetIntFromEdit(HWND hWnd,const int iMinimum,const int iMaximum){
    TCHAR szNumber[10]={0};
    int iResult=0;

    GetWindowText(hWnd,szNumber,sizeof(szNumber)-1);
    iResult=_ttoi(szNumber);
    //最小値
    if(iResult<iMinimum)iResult=iMinimum;
    //最大値
    if(iResult>iMaximum)iResult=iMaximum;
    return iResult;
}

//数値を文字列に変換してエディットボックスに入力
bool SetIntToEdit(HWND hEdit,const int iNumber){
    TCHAR* pszNumber=NULL;

    pszNumber=(TCHAR*)malloc(GetIntLength(iNumber)*sizeof(TCHAR)+1);
    if(pszNumber==NULL)return false;
    wsprintf(pszNumber,_T("%d"),iNumber);
    SetWindowText(hEdit,pszNumber);
    free(pszNumber);
    pszNumber=NULL;
    return true;
}

//画面中央にダイアログを表示
void SetCenterWindow(HWND hDlg){
    RECT rc;
    GetWindowRect(hDlg,&rc);
    SetWindowPos(hDlg,
                NULL,
                (GetSystemMetrics(SM_CXSCREEN)-(rc.right-rc.left))>>1,
                (GetSystemMetrics(SM_CYSCREEN)-(rc.bottom-rc.top))>>1,
                -1,
                -1,
                SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE
    );
    return;
}

//ツールバー内のボタンの状態を調べる
bool GetStateButtonToolBar(HWND hToolBar,int iButtonId,LONG lState){
    LRESULT lResult=SendMessage(hToolBar,TB_GETSTATE,(WPARAM)iButtonId,(LPARAM)0);

    if(lResult&lState)return true;
    else return false;
}

//エディットボックスの拡張子を除くファイル名を選択
void SelectEditExcludeExtension(HWND hEdit){
    int iDotPos=0;
    TCHAR szFileName[MAX_PATH]={0};

    GetWindowText(hEdit,szFileName,ARRAY_SIZEOF(szFileName));//エディットボックスから取得
    iDotPos=path::LocateLastCharacter(szFileName,_T('.'));//'.'の位置を検索
    SetFocus(hEdit);//これがないとEM_SETSELが動作しない
    SendMessage(hEdit,EM_SETSEL,(WPARAM)0,(LPARAM)iDotPos);//拡張子の部分を除いて選択
    return;
}

//ファイルのバージョンを取得
void GetFileVersion(TCHAR* pszResult,const TCHAR* pszFilePath){
    DWORD dwHandle;
    LPVOID lpBuffer=NULL;
    DWORD dwSize=GetFileVersionInfoSize(pszFilePath,&dwHandle);

    if(dwSize<=0||!(lpBuffer=GlobalAlloc(GPTR,dwSize))){
        if(path::FileExists(pszFilePath)){
            _tcscpy(pszResult,_T("OK          "));
        }else{
            _tcscpy(pszResult,_T("------------"));
        }
        return;
    }

    LPVOID lpResult=NULL;
    UINT uiLength=0;
    if(GetFileVersionInfo(pszFilePath,0,dwSize,lpBuffer)){
        VerQueryValue((const LPVOID)lpBuffer,_T("\\"),&lpResult,&uiLength);
        VS_FIXEDFILEINFO* pVSFileInfo=(VS_FIXEDFILEINFO*)lpResult;
        DWORD dwFileVerMS=pVSFileInfo->dwFileVersionMS;
        DWORD dwFileVerLS=pVSFileInfo->dwFileVersionLS;
        wsprintf(pszResult,_T("%ld.%02lu.%ld.%02lu"),dwFileVerMS>>16,dwFileVerMS&0xffff,dwFileVerLS>>16,dwFileVerLS&0xffff);
    }else{
        _tcscpy(pszResult,_T("---------"));
    }
    GlobalFree(lpBuffer);
    return;
}

//XPスタイルのソートを行う
int _StrCmpLogicalW(PCWSTR psz1,PCWSTR psz2){
    int iResult=0;
    TCHAR szDllPath[MAX_PATH]={0};

    typedef DWORD(WINAPI *PSTRCMPLOGICALW)(PCWSTR,PCWSTR);
    PSTRCMPLOGICALW pStrCmpLogicalW;
    GetSystemDirectory(szDllPath,MAX_PATH);
    _tcscat(szDllPath,_T("\\shlwapi.dll"));
    HMODULE hDll=LoadLibrary(szDllPath);

    if(hDll){
        pStrCmpLogicalW=(PSTRCMPLOGICALW)GetProcAddress(hDll,"StrCmpLogicalW");
        if(pStrCmpLogicalW){
            iResult=pStrCmpLogicalW(psz1,psz2);
        }
        FreeLibrary(hDll);
    }
    return iResult;
}

//IDからめニュー内のアイテムの場所を取得
int _GetMenuPosFromID(HMENU hmenu,UINT id){
    int iResult=0;
    TCHAR szDllPath[MAX_PATH]={0};

    typedef DWORD(WINAPI *PGETMENUPOSFROMID)(HMENU,UNIT);
    PGETMENUPOSFROMID pGetMenuPosFromID;
    GetSystemDirectory(szDllPath,MAX_PATH);
    _tcscat(szDllPath,_T("\\shlwapi.dll"));
    HMODULE hDll=LoadLibrary(szDllPath);

    if(hDll){
        pGetMenuPosFromID=(PGETMENUPOSFROMID)GetProcAddress(hDll,"GetMenuPosFromID");
        if(pGetMenuPosFromID){
            iResult=pGetMenuPosFromID(hmenu,id);
        }
        FreeLibrary(hDll);
    }
    return iResult;
}

//文字列をクリップボードにコピー
bool SetClipboardText(HWND hWnd,const TCHAR* pszText,int iLength){
    bool bResult=false;
    int iBufferSize=0;

    if(!OpenClipboard(hWnd))return false;

    iBufferSize=iLength*sizeof(TCHAR)+sizeof(TCHAR);
    HGLOBAL hGlobal=GlobalAlloc(GMEM_MOVEABLE,iBufferSize);
    if(hGlobal!=NULL){
        LPVOID lpMemory=static_cast<LPVOID>(GlobalLock(hGlobal));
        memcpy(lpMemory,pszText,iBufferSize);
        GlobalUnlock(hGlobal);
        EmptyClipboard();
#ifdef UNICODE
        if(SetClipboardData(CF_UNICODETEXT,hGlobal))bResult=true;
#else
        if(SetClipboardData(CF_TEXT,hGlobal))bResult=true;
#endif
    }
    CloseClipboard();
    return bResult;
}

//ビジュアルスタイルが有効かどうか確認
bool IsVisualStyle(){
    bool bResult=false;
    TCHAR szDllPath[MAX_PATH]={0};

    GetSystemDirectory(szDllPath,MAX_PATH);
    _tcscat(szDllPath,_T("\\UxTheme.dll"));
    HMODULE hUxThemeDll=LoadLibrary(szDllPath);
    if(hUxThemeDll){
        typedef bool(*ISAPPTHEMEDPROC)();
        ISAPPTHEMEDPROC pIsAppThemed;
        pIsAppThemed=(ISAPPTHEMEDPROC)GetProcAddress(hUxThemeDll,"IsAppThemed");
        if(pIsAppThemed){
            bResult=pIsAppThemed();
        }
        FreeLibrary(hUxThemeDll);
    }
    return bResult;
}

//背景ブラシを更新(ビジュアルスタイルが有効な際コントロールの描画がおかしくなる問題を防止)
void UpdateBackgroundBrush(HWND hWnd,HBRUSH hBrush,bool bVisualStyle){
    //前回のブラシを破棄
    if(hBrush){
        DeleteObject(hBrush);
    }
    hBrush=NULL;

    if(bVisualStyle){//ビジュアルスタイルが有効であれば
        RECT rc;

        GetWindowRect(hWnd,&rc);
        HDC hDC=GetDC(hWnd);
        //互換性のあるDCを作成
        HDC hDCMem=CreateCompatibleDC(hDC);
        HBITMAP hBitmap=CreateCompatibleBitmap(hDC,rc.right-rc.left,rc.bottom-rc.top);
        HBITMAP hBitmapOld=(HBITMAP)(SelectObject(hDCMem,hBitmap));
        //hWndにhDCMemによる描画を通知
        SendMessage(hWnd,WM_PRINTCLIENT,(WPARAM)(hDCMem),(LPARAM)(PRF_ERASEBKGND|PRF_CLIENT|PRF_NONCLIENT));
        //hBitmapからビットマップパターンを持つ論理ブラシを作成
        hBrush=CreatePatternBrush(hBitmap);
        SelectObject(hDCMem,hBitmapOld);
        DeleteObject(hBitmap);
        DeleteDC(hDCMem);
        ReleaseDC(hWnd,hDC);
    }
    return;
}

//数字の桁数を取得
int GetIntLength(int iNumber){
    int iResult=0;

    for(;iNumber!=0;iResult++)iNumber/=10;
    return iResult;
}

//16進数またはRGB表記の文字列をCOLORREF型に変換
COLORREF StringToCOLORREF(TCHAR* pszString){
    if(((pszString[0]==_T('#')&&lstrlen(pszString)==7)||
        (lstrlen(pszString)==6&&path::LocateFirstCharacter(pszString,_T(','))==-1))){
        //16進数値
        unsigned long ulResult=static_cast<unsigned long>(_tcstoul((pszString[0]==_T('#'))?pszString+1:pszString,NULL,16));
        return RGB(GetBValue(ulResult),GetGValue(ulResult),GetRValue(ulResult));
    }else if((pszString[0]!=_T('#')&&path::CountCharacter(pszString,_T(','))==2)){
        //RGB値
        int iR,iG,iB;
        iR=_ttoi(pszString);//r,g,bからrを取り出す
        pszString+=path::LocateFirstCharacter(pszString,_T(','))+1;//rとgの間の','+1に移動
        iG=_ttoi(pszString);//g,bからgを取り出す
        pszString+=path::LocateFirstCharacter(pszString,_T(','))+1;//gとbの間の','+1に移動
        iB=_ttoi(pszString);//bからbを取り出す
        return RGB(iR,iG,iB);
    }
    return static_cast<COLORREF>(_ttol(pszString));
}

//COLORREF型を16進数表記の文字列に変換
bool COLORREFToHex(TCHAR* pszResult,COLORREF color){
    wsprintf(pszResult,_T("#%02X%02X%02X"),GetRValue(color),GetGValue(color),GetBValue(color));
    return true;
}

//COLORREF型をRGB表記の文字列に変換
bool COLORREFToRGB(TCHAR* pszResult,COLORREF color){
    wsprintf(pszResult,_T("%d,%d,%d"),GetRValue(color),GetGValue(color),GetBValue(color));
    return true;
}

//標準のGUIフォントを作成
HFONT CreateGUIFont(LPCTSTR lpszFontName,int iSize,int iStyle){
    NONCLIENTMETRICS ncMetrics;
    LOGFONT lgFont;

    memset(&ncMetrics,0,sizeof(NONCLIENTMETRICS));
    ncMetrics.cbSize=sizeof(NONCLIENTMETRICS);
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(NONCLIENTMETRICS),&ncMetrics,0);
    memcpy(&lgFont,&ncMetrics.lfMessageFont,sizeof(LOGFONT));

    if(lstrlen(lpszFontName))_tcscpy(lgFont.lfFaceName,lpszFontName);
    if(iSize>0)lgFont.lfHeight=iSize;
    if(iStyle&SFONT_BOLD)lgFont.lfWeight=FW_BOLD;
    if(iStyle&SFONT_ITALIC)lgFont.lfItalic=true;
    if(iStyle&SFONT_UNDERLINE)lgFont.lfUnderline=true;
    if(iStyle&SFONT_STRIKEOUT)lgFont.lfStrikeOut=true;

    return CreateFontIndirect(&lgFont);
}

//論理フォントをコントロールに適用
void SetFont(HWND hWnd,LPCTSTR lpszFontName,int iSize,int iStyle){
    HFONT hFont;
    HDC hDC=GetDC(hWnd);

    hFont=CreateGUIFont(lpszFontName,iSize,iStyle);
    SetBkMode(hDC,OPAQUE);
    SendMessage(hWnd,WM_SETFONT,(WPARAM)hFont,true);
    ReleaseDC(hWnd,hDC);
    return;
}

//現在のフォントサイズを取得
int GetCurrentFontSize(HWND hWnd){
    TEXTMETRIC TextMetric;

    HDC hDC=GetDC(hWnd);
    SelectObject(hDC,reinterpret_cast<void*>(SendMessage(hWnd,WM_GETFONT,(WPARAM)0,(LPARAM)0)));
    GetTextMetrics(hDC,&TextMetric);

    ReleaseDC(hWnd,hDC);
    return TextMetric.tmHeight;
}

//バージョンファイルを元に最新版かどうか比較
int CheckLatestVersion(TCHAR* pszApplicationName,TCHAR* pszVersionFilePath,TCHAR* pszResultFileName,TCHAR* pszResultUrl){
    TCHAR szOldVersion[256];

    //現在のバージョンを取得
    DWORD dwHandle;
    LPVOID lpBuffer=NULL;
    DWORD dwSize=GetFileVersionInfoSize(pszApplicationName,&dwHandle);

    if(dwSize<=0||!(lpBuffer=GlobalAlloc(GPTR,dwSize))){
        return -1;
    }

    LPVOID lpResult=NULL;
    UINT uiLength=0;
    if(GetFileVersionInfo(pszApplicationName,0,dwSize,lpBuffer)){
        VerQueryValue((const LPVOID)lpBuffer,_T("\\"),&lpResult,&uiLength);
        VS_FIXEDFILEINFO* pVSFileInfo=(VS_FIXEDFILEINFO*)lpResult;
        DWORD dwFileVerMS=pVSFileInfo->dwFileVersionMS;
        DWORD dwFileVerLS=pVSFileInfo->dwFileVersionLS;
        wsprintf(szOldVersion,_T("%ld.%lu.%ld.%lu"),dwFileVerMS>>16,dwFileVerMS&0xffff,dwFileVerLS>>16,dwFileVerLS&0xffff);
    }
    GlobalFree(lpBuffer);


    HINTERNET hInternet=InternetOpen(_T("Check Latest Version"),INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
    if(hInternet==NULL)return -1;

    HINTERNET hUrl=InternetOpenUrl(hInternet,pszVersionFilePath,NULL,0,INTERNET_FLAG_RELOAD,0);
    if(hUrl==NULL){
        InternetCloseHandle(hInternet);
        return -1;
    }

    //バージョンファイルを読み込む
    char szBufferA[256];
    DWORD dwReadSize;
    InternetReadFile(hUrl,szBufferA,sizeof(szBufferA),&dwReadSize);
    szBufferA[dwReadSize]='\0';

    InternetCloseHandle(hUrl);
    InternetCloseHandle(hInternet);

    TCHAR szNewVersion[128]={0};
    TCHAR szFileName[128]={0};
    TCHAR szDownUrl[128]={0};


#ifdef UNICODE
    wchar_t szBufferW[128]={0};
    MultiByteToWideChar(CP_ACP,0,szBufferA,-1,szBufferW,(int)(sizeof(szBufferW)/sizeof(wchar_t))-1);
    _stscanf((const wchar_t*)&szBufferW,_T("%[^,],%[^,],%[^,]"),szNewVersion,szFileName,szDownUrl);
#else
    _stscanf((const char*)&szBufferA,_T("%[^,],%[^,],%[^,]"),szNewVersion,szFileName,szDownUrl);
#endif

    dprintf(_T("szNewVersion=%s\n"),szNewVersion);
    dprintf(_T("szFileName=%s\n"),szFileName);
    dprintf(_T("szDownUrl=%s\n"),szDownUrl);

    _tcscpy(pszResultFileName,szFileName);
    _tcscpy(pszResultUrl,szDownUrl);

    TCHAR* pszOldVersion=szOldVersion;
    TCHAR* pszNewVersion=szNewVersion;
    int iOldVersion=_ttoi(pszOldVersion);
    int iNewVersion=_ttoi(pszNewVersion);

    dprintf(_T("old=%s,ver=%s,old=%d,ver=%d\n"),pszOldVersion,pszNewVersion,iOldVersion,iNewVersion);
    //<0>,0,0,0をチェック
    if(iOldVersion<iNewVersion)return 1;

    for(int i=0;i<3;i++){
        //0,<0>,0,0から0,0,0,<0>をチェック
        pszOldVersion+=path::LocateFirstCharacter(pszOldVersion,L'.')+1;
        pszNewVersion+=path::LocateFirstCharacter(pszNewVersion,L'.')+1;
        iOldVersion=_ttoi(pszOldVersion);
        iNewVersion=_ttoi(pszNewVersion);

        dprintf(_T("old=%s,ver=%s,old=%d,ver=%d\n"),pszOldVersion,pszNewVersion,iOldVersion,iNewVersion);

        if(iOldVersion<iNewVersion)return 1;
        else if(iOldVersion>iNewVersion)return 0;
    }

    return 0;
}

//ファイルをダウンロード
bool DownloadFile(TCHAR* pszServer,TCHAR* pszFileName,TCHAR* pszUrl,HWND hStatusBar,HWND hStatusProgressBar){
    HINTERNET hInternet;

    dprintf(_T("pszFileName=%s,pszServer=%s,pszUrl=%s\n"),pszFileName,pszServer,pszUrl);

    if(InternetAttemptConnect(0)!=ERROR_SUCCESS)return false;

    hInternet=InternetOpen(_T("Update"),INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
    if(hInternet==NULL)return false;

    //サーバに接続
    HINTERNET hConnect;

    hConnect=InternetConnect(hInternet,pszServer,INTERNET_DEFAULT_HTTP_PORT,NULL,NULL,INTERNET_SERVICE_HTTP,0,NULL);
    if(hConnect==NULL){
        InternetCloseHandle(hInternet);
        return false;
    }

    //HTTPリクエストを作成
    HINTERNET hRequest;

    hRequest=HttpOpenRequest(hConnect,_T("GET"),pszUrl,NULL,NULL,NULL,INTERNET_FLAG_RELOAD|INTERNET_FLAG_KEEP_CONNECTION,NULL);
    if(hRequest==NULL){
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hInternet);
        return false;
    }

    bool bResult=false;
    
    //HTTPリクエストを送信
    if((bResult=HttpSendRequest(hRequest,NULL,0,NULL,0))){
        long lFileSize;
        DWORD dwSize=sizeof(long);//4096;
        HANDLE hFile;
        char szBuffer[4096+16];
        bool bProgress=false;

        //ファイルサイズを取得
        if(HttpQueryInfo(hRequest,HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER,&lFileSize,&dwSize,NULL)){
            bProgress=true;
        }
        dprintf(_T("FileSize:%d\n"),lFileSize);

        //プログレスバーの設定
        if(hStatusProgressBar!=NULL&&lFileSize>0){
            //範囲指定
            PostMessage(hStatusProgressBar,PBM_SETRANGE,(WPARAM)0,MAKELPARAM(0,100));
            //1Stepは1
            PostMessage(hStatusProgressBar,PBM_SETSTEP,(WPARAM)1,(LPARAM)0);
        }

        //ファイルを作成
        DWORD dwDownloaded=0;

        hFile=CreateFile(pszFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
        if(hFile!=INVALID_HANDLE_VALUE){
            TCHAR szMsg[128]={0};
            DWORD dwByte=0;
            DWORD dwWritten;

            while(1){
                InternetReadFile(hRequest,szBuffer,4096,&dwByte);
                if(dwByte==0)break;

                //ファイルの書き込み
                WriteFile(hFile,szBuffer,dwByte,&dwWritten,NULL);

                dwDownloaded+=dwByte;

                if(hStatusBar!=NULL){
                    wsprintf(szMsg,_T("%d byte"),dwDownloaded);
                    PostMessage(hStatusBar,SB_SETTEXT,0|2,(LPARAM)szMsg);
                }

                if(hStatusProgressBar!=NULL)PostMessage(hStatusProgressBar,PBM_SETPOS,(WPARAM)int(dwDownloaded*100/lFileSize),(LPARAM)0);
                dprintf(_T("%d Byte Downloaded.\n"),dwDownloaded);

                if(!g_bWorking)break;
            }
        }
        FlushFileBuffers(hFile);
        CloseHandle(hFile);
    }
    InternetCloseHandle(hRequest);
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hInternet);
    return bResult;
}

//最新版にアップデート
bool UpdateLatestVersion(HWND hWnd,HINSTANCE hInstance,HWND hStatusBar,HWND hStatusProgressBar,bool bNotFoundMessage){
    TCHAR szApplicationName[MAX_PATH]={0};

    if(GetModuleFileName(NULL,szApplicationName,sizeof(szApplicationName))){
        PathFindFileName(szApplicationName);

        dprintf(_T("***Update***\n"));

        TCHAR szVersionFilePath[MAX_PATH]={0};//URL
        TCHAR szServer[128]={0};
        TCHAR szFileName[128]={0};
        TCHAR szUrl[256]={0};

        if(hStatusBar!=NULL)PostMessage(hStatusBar,SB_SETTEXT,0|1,(LPARAM)_T("最新版を確認しています..."));

        //現在はwww16.atpages.jp
        LoadString(hInstance,IDS_SERVER,(LPTSTR)&szServer,sizeof(szServer)-1);
        //現在はhttp://www16.atpages.jp/rayna/Ashley/version.dat
        LoadString(hInstance,IDS_VERSION_FILE,(LPTSTR)&szVersionFilePath,sizeof(szVersionFilePath)-1);

        int iResult=CheckLatestVersion(szApplicationName,szVersionFilePath,szFileName,szUrl);

        if(iResult==1){
            dprintf(_T("New Version found.\n"));
            if(hStatusBar!=NULL)PostMessage(hStatusBar,SB_SETTEXT,0|1,(LPARAM)_T("最新版が見つかりました"));
            int iResult=IDNO;
            iResult=MessageBox(hWnd,_T("最新版が公開されているようです。\n\nダウンロードしますか?"),_T("アップデート"),MB_YESNO|MB_ICONQUESTION);
            if(iResult==IDNO){
                iResult=MessageBox(hWnd,_T("このバージョンにはとんでもないバグが含まれていて、\nえっちぃファイルを根こそぎ削除するかもしれません。\n\nダウンロードしますか?"),_T("アップデート"),MB_YESNO|MB_ICONQUESTION);
            }
            if(iResult==IDYES){
                if(!SaveFileDialog(hWnd,
                                   szFileName,
                                   ARRAY_SIZEOF(szFileName)+1,
                                   _T("書庫ファイル (*.zip)\0*.zip\0\0"),
                                   _T("保存先を選択してください"))){
                    return false;
                }
                if(hStatusBar!=NULL)PostMessage(hStatusBar,SB_SETTEXT,0|1,(LPARAM)_T("ダウンロードしています..."));
                if(!DownloadFile(szServer,szFileName,szUrl,hStatusBar,hStatusProgressBar)){
                    MessageBox(hWnd,_T("ファイルのダウンロードに失敗しました。"),_T("アップデート"),MB_ICONSTOP);
                    return false;
                }
                if(hStatusBar!=NULL)PostMessage(hStatusBar,SB_SETTEXT,0|1,(LPARAM)_T("ダウンロードが完了しました"));
            }
        }else if(iResult==0){
            if(bNotFoundMessage){
                if(IDYES==MessageBox(hWnd,_T("最新版を使用しています。\n\nどうやら作者はバグにまだ気付いていないようです。\n作者に報告しますか?"),_T("アップデート"),MB_YESNO|MB_ICONQUESTION)){
                    //ホームページにアクセス
                    TCHAR szBuffer[64]={0};

                    LoadString(hInstance,IDS_URL,(LPTSTR)&szBuffer,sizeof(szBuffer)-1);
                    ShellExecute(NULL,_T("open"),szBuffer,NULL,NULL,SW_SHOWNORMAL);
                }
            }
        }else{
            MessageBox(hWnd,_T("エラーが発生したため、バージョンチェックを行うことが出来ません。\nインターネットに接続されているか確認して下さい。"),_T("アップデート"),MB_ICONSTOP);
        }
    }
    return true;
}

//文字列をすべて置換する
void AllReplace(TCHAR* pszDest,const TCHAR* pszSrc,const TCHAR* pszPattern,const TCHAR* pszReplace){
    const tstring strSrc(pszSrc);
    const tstring strPattern(pszPattern);
    const tstring strReplace(pszReplace);

    tstring strResult;
    tstring::size_type iBeforePosition=0;
    tstring::size_type iPosition=0;
    tstring::size_type iLength=strPattern.size();

    while((iPosition=strSrc.find(strPattern,iPosition))!=tstring::npos){
        strResult.append(strSrc,iBeforePosition,iPosition-iBeforePosition);
        strResult.append(strReplace);
        iPosition+=iLength;
        iBeforePosition=iPosition;
    }
    strResult.append(strSrc,iBeforePosition,strSrc.size()-iBeforePosition);
    _tcscpy(pszDest,strResult.c_str());
    return;
}

//四角形を指定した純色で塗りつぶす
void FillSolidRect(HDC hDC,RECT *prcRect,COLORREF clColorRef){
    SetBkColor(hDC,clColorRef);
    ExtTextOut(hDC,0,0,ETO_OPAQUE,prcRect,NULL,0,NULL);
    return;
}

Home > ソフトウェア > Ashley > Ashley130.zip/Ashley130.exe > Src > Function.cpp