VisualStudio/VC++

VBマクロはよくわかりません

VisualStudioマクロ

古いマルチバイト文字セットのソースを(とりあえず)Unicode用にする

ネットでVC++のサンプルをほじくりかえしてると昔の非Unicodeのものがガンガンヒットする。が、VisualStudio 2005以降Unicodeが標準だしコンパイラの設定を変えてもいいけど、それもまた厄介なこともあるのでとりあえず通り一遍の置換えをするマクロを作った。

VisualStudio 2005用です。他の環境では試していません。マクロエクスプローラ右クリック→新しいマクロプロジェクト→マクロIDEに貼り付けてどうぞ。ReplaceForUnicodeAllで開いてるソースに対して実行します。ReplaceForUnicodeで選択範囲のみに実行します。

やってることとしては、

です。APIの置換えは、よく使うやつしか書いてないので全部のを書きたい人は これ を見てください。strcpy()->_tcscpy()じゃなくてlstrcpy()なのはなんか理由があったけど忘れました。確か実行ファイルのサイズが小さくなる気がする。

あとlstrlen()を無言で置き換えてますがそのまま使うとやばい時があります。元のソースで


int length = lstrlen(lpStr);

だとしたら、


length = (lstrlen(lpStr))*sizeof(TCHAR);

としないといろんな長さが半分になって死にます。文字数を要求してる時は大丈夫ですが、バイト数を要求してるとバッファオーバーです。_tcsncpy()もまずい。ReadFile()の末端処理やGetWindowTextLength()なども。それでもうまい事いかなかったらあきらめてコンパイラの設定をマルチバイト文字にしてください。変えられるような置換えのはずなので。ちなみに他にもUnicode移行時にひっかかった所がありますがまた今度。

ところで、最新のVisualStudio用VBAの正規表現ヘルプがどこにあるのかわかりません。古いのはありましたが表現が変わっており、しかたなく全部試してました。VSマクロは難しいです。


'ReplaceUnicode.vb
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics

Public Module ReplaceUnicode

    Sub ReplaceForUnicodeAll()

        ReplacePattern(DTE, True)

    End Sub

    Sub ReplaceForUnicode()

        ReplacePattern(DTE, False)

    End Sub

    Sub SelectRange(ByVal txtSel As TextSelection, ByVal topLine As Integer, ByVal diff As Integer)
        txtSel.MoveToLineAndOffset(topLine, 1)
        txtSel.LineDown(True, diff)
    End Sub

    Sub MySelect(ByVal txtSel As TextSelection, ByVal all As Boolean, ByVal topLine As Integer, ByVal diff As Integer)
        If (all) Then
            txtSel.SelectAll()
        Else
            SelectRange(txtSel, topLine, diff)
        End If
    End Sub


    Sub ReplacePattern(ByVal dte As DTE, ByVal all As Boolean)

        Dim txtSel As TextSelection = _
            CType(dte.ActiveDocument.Selection, TextSelection)

        Dim topLine As Integer = txtSel.AnchorPoint.Line
        Dim endLine As Integer = txtSel.ActivePoint.Line
        Dim diff As Integer = endLine - topLine


        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("WinMain", "_tWinMain", vsFindOptions.vsFindOptionsMatchCase)

        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("\#include \<windows\.h\>", "\#include \<windows\.h\>\n\#include \<tchar\.h\>", vsFindOptions.vsFindOptionsRegularExpression)

        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("msg.wParam", "(int)msg.wParam")

        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("wc.hbrBackground = GetStockObject", "wc.hbrBackground = (HBRUSH)GetStockObject")

        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("(LPCSTR)", "")

        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("LPSTR", "LPTSTR", vsFindOptions.vsFindOptionsMatchCase)

        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("LPCSTR", "LPCTSTR", vsFindOptions.vsFindOptionsMatchCase)

        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("char ", "TCHAR ", vsFindOptions.vsFindOptionsMatchCase)

        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("{[^\\]}""""", "\1_T("""")", vsFindOptions.vsFindOptionsRegularExpression)

        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("{[^\\]}{""([^""]|(\\""))*[^\\]""}", "\1_T(\2)", vsFindOptions.vsFindOptionsRegularExpression)


        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("strcpy", "lstrcpy", vsFindOptions.vsFindOptionsMatchWholeWord)
        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("strlen", "lstrlen", vsFindOptions.vsFindOptionsMatchWholeWord)
        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("strcat", "lstrcat", vsFindOptions.vsFindOptionsMatchWholeWord)

        '#include <tchar.h>
        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("sprintf", "wsprintf", vsFindOptions.vsFindOptionsMatchWholeWord)
        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("strcmp", "_tcscmp", vsFindOptions.vsFindOptionsMatchWholeWord)
        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("stricmp", "_tcsicmp", vsFindOptions.vsFindOptionsMatchWholeWord)
        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("strncpy", "_tcsncpy", vsFindOptions.vsFindOptionsMatchWholeWord)
        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("strstr", "_tcsstr", vsFindOptions.vsFindOptionsMatchWholeWord)
        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("strrchr", "_tcsrchr", vsFindOptions.vsFindOptionsMatchWholeWord)
        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("strchr", "_tcschr", vsFindOptions.vsFindOptionsMatchWholeWord)
        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("strtok", "_tcstok", vsFindOptions.vsFindOptionsMatchWholeWord)
        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("atof", "_tstof", vsFindOptions.vsFindOptionsMatchWholeWord)
        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("atoi", "_tstoi", vsFindOptions.vsFindOptionsMatchWholeWord)
        MySelect(txtSel, all, topLine, diff)
        txtSel.ReplacePattern("itoa", "_itot", vsFindOptions.vsFindOptionsMatchWholeWord)

    End Sub

End Module