3

私は Javascript 開発者なので、気楽にやってください! フレームワークでの印刷を可能にする C++ のパッチだけを作成しようとしています。私は Unicode でコンパイルしていますが、私の調査によると、それが私を台無しにしています。

これは、私が複雑にしすぎている比較的単純なことだと思います。アプリケーションにはstd::string、現在のプリンター名を含む があります。スクリプトは最初にそれが設定されていないかどうかをチェックします(設定されている場合は、GetDefaultPrinterどの出力を利用しますかLPTSTR)。最後に、スクリプトは thanstd::stringまたは のいずれかを受け取り、 for にLPTSTR変換します。LPCTSTRCreateDC

これが私のコードです:

std::string PrinterName = window->getPrinter();
LPDWORD lPrinterNameLength;
LPWSTR szPrinterName;
LPCTSTR PrinterHandle;

if (PrinterName == "unset") {
    GetDefaultPrinter( szPrinterName, &lPrinterNameLength );
    PrinterHandle = szPrinterName; //Note sure the best way to convert here
} else {
    PrinterHandle = PrinterName.c_str();
}
HDC hdc = CreateDC( L"WINSPOOL\0", PrinterHandle, NULL, NULL);

コンパイル時に、変換エラーのみが発生します。そのような

パラメーター 2 を LPDWORD * から LPDWORD (GetDefaultPrinter) に変換できません

「const char *」から「LPCTSTR」に変換できません (PrinterHandle = PrinterName.c_str() 行で)

私はこれについてかなりの SO 調査を行いましたが、具体的な解決策は思いつきませんでした。

どんな助けでも大歓迎です!

4

2 に答える 2

2

"Unicode" (ワイド文字列) 用にコンパイルされている場合でも、API 関数の "ANSI" (ナロー文字列) バージョンを呼び出すことができます。Windows が変換を行い、内部でワイド文字バージョンを呼び出します。

たとえば、 のようなほとんどの Windows APICreateDCには、実際にはその名前の関数はありません。代わりに、実際の関数名であるまたはにCreateDC展開されるという名前のマクロがあります。「Unicode」用にコンパイルすると、マクロはバージョン (OS のすべての最新バージョンのネイティブ バージョン) に展開されます。Unicode 用にコンパイルされているかどうかに関係なく、いずれかのバージョンを明示的に呼び出すことを妨げるものは何もありません。ほとんどの場合、バージョンは単純にナロー文字列をワイド文字列に変換し、対応するバージョンを呼び出します (ウィンドウの作成に関連するいくつかの注意点がありますが、DC には適用されないと思います)。CreateDCACreateDCW-W-A-W

std::string PrinterName = window->getPrinter();
if (PrinterName == "unset") {
  char szPrinterName[MAX_PATH];  // simplified for illustration
  DWORD cchPrinterNameLength = ARRAYSIZE(szPrinterName);
  GetDefaultPrinterA(szPrinterName, &cchPrinterNameLength);
  PrinterName = szPrinterName;
}

HDC hdc = CreateDCA("WINSPOOL", PrinterName.c_str(), NULL, NULL);
于 2013-01-26T00:16:40.467 に答える
2

まず、コメントで述べたように、適切な方法は a を作成しDWORDてアドレスを渡すことです。

DWORD lpPrinterNameLength;
...
GetDefaultPrinter(..., &lpPrinterNameLength);

なぜそうなのかは、数値を使用および変更できるようにするためです。

入力時に、pszBuffer バッファーのサイズを文字数で指定します。出力時に、終了のヌル文字を含むプリンター名文字列のサイズ (文字数) を受け取ります。

DWORD必要ですが、関数は渡された変数の数値を変更するため、これらの変更が呼び出し元に反映されるように、関数は変数のアドレスを変更する必要があります。


次に、window->getPrinter()ナロー文字列を返し、 を使用しUNICODEているため、関数がワイド文字列を取るため、ナロー文字列からワイド文字列に変換する必要があります。これを行うにはいくつかの方法があり (ildjarn のコメントで言及されている非常に簡単な方法など)、この方法でさえ C++11 の方がわずかに優れていますが、前述の注意事項はその方がより適切に適用されますがMultiByteToWideChar、C を使用します。 ++03:

std::wstring narrowToWide(const std::string &narrow) {
    std::vector<wchar_t> wide;

    int length = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, narrow.c_str(), -1, NULL, 0);
    if (!length) {
        //error
    }

    wide.resize(length);
    if (!MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, narrow.c_str(), -1, &wide[0], length)) {
        //error, should probably check that the number of characters written is consistent as well
    }

    return std::wstring(wide.begin(), wide.end());
}

...

std::wstring PrinterName = narrowToWide(window->getPrinter());
//rest is same, but should be L"unset"
CreateDC( L"WINSPOOL\0", PrinterHandle, NULL, NULL);
于 2013-01-25T22:30:12.037 に答える