トップページ > 記事閲覧
【機能要望】文字単位の文字色変更、文字の中央寄せ・右寄せ
名前:was-blue.0793 日時: 2018/09/28 23:37

ご多忙中のところ申し訳ございませんが、機能の要望です。 DrawStringで描画される文字列を文字単位で文字色を変更して表示したい時があります。 そのため、文字単位で文字色を変更できる文字列描画関数の追加を要望します。 例えば、DrawStringColorCharacter(int x, int y, const TCHAR* str, size_t strlength, unsigned int* colorcodearray, size_t colorcodearraylength)のような関数です。 また、DrawStringで描画される文字列が改行されると全てが左寄せになりますが、これを中央寄せ、右寄せにしたいことがあります。 DrawStringに、改行時の文字を寄せる方向の引数の追加も併せて要望します。 この機能要望ですが、文字列を寄せる方向については需要があまりないかもしれないので、実装に時間がかかっても問題ありません。 また、ご多忙中とは思いますので、実装の目処が付いたときに実装していただけると幸いです。
メンテ

Page: 1 |

Re: 【機能要望】文字単位の文字色変更、文字の中央寄せ・右寄せ ( No.1 )
名前:MOR 日時:2018/10/01 00:57

相変わらず超適当ですが Windows(x86, x64, MBCS, 2バイトUnicode), Android(x86) でビルドできるようにしました。 なお、DrawStringで改行したときに何ドット下がるかがAndroid版とWindows版で違う(?)ようなので、手動で数値設定するようにしました。 #include "DxLib.h" #include <vector> using namespace std; #define ALIGNMENT_LEFT 0 #define ALIGNMENT_CENTER 1 #define ALIGNMENT_RIGHT 2 // 文字ごとの色変更版DrawString // // bApplyCRColor=TRUEなら、改行文字('\n')にもダミー色を割り当ててあるとして処理 // 位置寄せ指定は『改行後の文字』が対象なので、一行目は左寄せ固定。 // Unicodeは『1文字=2バイトのUnicode』のみが対象。1文字=4バイトのUnicodeでは動作しない。 // nLineInterval=改行の際のドット数 (DrawStringの改行ドット数はWindowsとAndroidで挙動が違うが法則がわからなかったので手動にした) int DrawStringWithColorArray(int x, int y, const TCHAR* pStr, unsigned int* pColorCodeArray, int bApplyCRColor, int nLineInterval, int nPosAlignment = ALIGNMENT_LEFT) { if (pStr == NULL) return -1; if (pColorCodeArray == NULL) return -1; #ifdef _WINDOWS #ifdef UNICODE const TCHAR *lpStr = pStr; #else LPSTR lpStr = (LPSTR)pStr; #endif #else LPSTR lpStr = (LPSTR)pStr; #endif vector<vector<TCHAR>> vct; vector<TCHAR> vct0; int SizeX, SizeY = 0, ColorBitDepth = 0; RECT rc; DxLib::GetDrawArea(&rc); SizeX = rc.right; // スクリーンサイズで寄せ位置を設定したい場合は↓ // DxLib::GetScreenState(&SizeX, &SizeY, &ColorBitDepth); int nFSize = DxLib::GetFontSize(), xs = x; size_t uiSize = DxLib::strlen2Dx(pStr); // 文字数取得(UTF-8でもここは文字数が返る) unsigned int uiCL = 0, ui2 = 0; int tt = 0; int CharBytes = 0; TCHAR c; TCHAR cc[10]; for (unsigned int ui = 0; ui < uiSize; ui++) { // まず、現在の文字が何バイトかを取得 #ifdef _WINDOWS #ifdef UNICODE CharBytes = 1; // 2バイトなのだが処理の都合上『1単位』とする。なお4バイトUnicodeは対象外 #else CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_SHIFTJIS, lpStr + ui2); #endif #endif #ifdef __ANDROID__ CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_UTF8, lpStr + ui2); #endif // 1バイトの場合 if (CharBytes == 1) { c = *(lpStr + ui2++); if (c == '\n') { vct.push_back(vct0); vct0.clear(); } else { vct0.push_back(c); } } else { // 多バイトの場合(改行は無く、文字のみ) for (int i = 0; i < CharBytes; i++) { c = *(lpStr + ui2++); vct0.push_back(c); } } } // 最後に \n が無い限り尻切れトンボになるのでそのまま足す if (vct0.size() > 0) { vct.push_back(vct0); vct0.clear(); } // ここまでで、行ごとに分割できている for (unsigned int i = 0; i < vct.size(); i++) { vct0 = vct[i]; // i行目 int xss = 0; if (nPosAlignment == ALIGNMENT_CENTER && i > 0) { for (unsigned int k = 0; k < vct0.size(); k++) { cc[0] = vct0[k]; #ifdef _WINDOWS #ifdef UNICODE CharBytes = 1; #else CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_SHIFTJIS, &cc[0]); #endif #endif #ifdef __ANDROID__ CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_UTF8, &cc[0]); #endif for (int m = 1; m < CharBytes; m++) { cc[m] = vct0[++k]; } cc[CharBytes] = '\0'; xss += DxLib::GetDrawStringWidth(cc, CharBytes); } x = (SizeX - xss) / 2; } else if (nPosAlignment == ALIGNMENT_RIGHT && i > 0) { for (unsigned int k = 0; k < vct0.size(); k++) { cc[0] = vct0[k]; #ifdef _WINDOWS #ifdef UNICODE CharBytes = 1; #else CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_SHIFTJIS, &cc[0]); #endif #endif #ifdef __ANDROID__ CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_UTF8, &cc[0]); #endif for (int m = 1; m < CharBytes; m++) { cc[m] = vct0[++k]; } cc[CharBytes] = '\0'; xss += DxLib::GetDrawStringWidth(cc, CharBytes); } x = SizeX - xss; } else { x = xs; } for (unsigned int j = 0; j < vct0.size(); j++) { cc[0] = vct0[j]; #ifdef _WINDOWS #ifdef UNICODE CharBytes = 1; #else CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_SHIFTJIS, &cc[0]); #endif #endif #ifdef __ANDROID__ CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_UTF8, &cc[0]); #endif for (int m = 1; m < CharBytes; m++) { cc[m] = vct0[++j]; } cc[CharBytes] = '\0'; DxLib::DrawString(x, y, cc, pColorCodeArray[uiCL++]); x += DxLib::GetDrawStringWidth(cc, CharBytes); } if (bApplyCRColor) uiCL++; y += nLineInterval; } return 0; } #ifdef _WINDOWS int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) #endif #ifdef __ANDROID__ int android_main(void) #endif { #ifdef _WINDOWS DxLib::ChangeWindowMode(TRUE); #endif if (DxLib::DxLib_Init() == -1) return -1; DxLib::SetBackgroundColor(128, 128, 128); DxLib::ClearDrawScreen(); DxLib::SetFontSize(20); DxLib::SetDrawScreen(DX_SCREEN_BACK); int SizeX, SizeY = 0, ColorBitDepth = 0; DxLib::GetScreenState(&SizeX, &SizeY, &ColorBitDepth); TCHAR *pStr = TEXT("Hello_\nC++_DXライブラリProgramming\nカナカナKANA"); size_t uiSize = DxLib::strlen2Dx(pStr); unsigned int *puiCArray = new unsigned int[uiSize], uiCounter = 0, uiCounter2 = 0; while (DxLib::ProcessMessage() == 0) { DxLib::ClearDrawScreen(); if (uiCounter++ % 30 == 0) { for (unsigned int ui = 0; ui < uiSize; ui++) { puiCArray[ui] = DxLib::GetColor((uiCounter2 + ui & 2) ? 255 : 0, (uiCounter2 + ui & 4) ? 255 : 0, (uiCounter2 + ui & 1) ? 255 : 0); } uiCounter2++; } // 通常描画 DxLib::DrawString(50, 50, pStr, DxLib::GetColor(255, 255, 255)); // 文字単位で色変更する int nLIntv = DxLib::GetFontSize() + 2; // 行間はお好みで設定してください。 DrawStringWithColorArray(50, 150, pStr, puiCArray, TRUE, nLIntv); // 改行でも色カウンターを進める場合・左寄せ DrawStringWithColorArray(50, 250, pStr, puiCArray, FALSE, nLIntv, ALIGNMENT_CENTER); // 改行では色カウンターを進めない場合・中央寄せ DxLib::SetDrawArea(0, 330, SizeX / 2, 450); // 描画範囲を狭く設定する DxLib::DrawBox(0, 0, SizeX, SizeY, DxLib::GetColor(132, 193, 255), TRUE); DrawStringWithColorArray(50, 350, pStr, puiCArray, TRUE, nLIntv, ALIGNMENT_RIGHT); // 改行でも色カウンターを進める場合・右寄せ・描画範囲指定 DxLib::SetDrawArea(0, 0, SizeX, SizeY); // 描画範囲を画面いっぱいに戻す DxLib::ScreenFlip(); } delete[]puiCArray; return DxLib::DxLib_End(); }
メンテ
Re: 【機能要望】文字単位の文字色変更、文字の中央寄せ・右寄せ ( No.2 )
名前:yumetodo 日時:2018/09/30 15:34

DxLibで中寄せで文字列を描画するのはどのくらい大変なんだろうか? ttps://qiita.com/yumetodo/items/8180d48b6fca18d78a90 に前に書いたものがあります。折返し対応。 これを描画部分だけいじれば良さそうです。
メンテ
Re: 【機能要望】文字単位の文字色変更、文字の中央寄せ・右寄せ ( No.3 )
名前:was-blue.0793 日時:2018/10/08 21:08

コメントが遅れました。 MORさんのコードを拝見する限り、文字単位での文字色変更はかなり難しい処理を必要としそうですね…… UTF-32など、1文字が確実に「1」となることが保証される文字コードでなければならなさそうですが、UTF-8が標準であるAndroidへの対応を考えるとほぼ無理でしょうし……
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存