質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

1290閲覧

TextOut()を使用し"hh:mm:ss"形式で描画した文字列(半角8文字)を" "(半角)9文字分で描画してクリアできない

dem0nmichik0

総合スコア37

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

1グッド

0クリップ

投稿2021/09/21 13:18

編集2021/09/21 16:56

困っていること

「TImage」コントロールのCanvasに時刻を「TextOut()」で表示後,表示更新のタイミングで「TextOut()」を使用して「" "(半角)を9つ」を描画して時刻表示をクリアしようとしていますが,下記のようになり,すべてクリアされず困っています。「調査して分かったこと」に記載したように解決方法はなんとなくわかったのですが,なぜ「TextOut()で" "(半角)を9つ」を描画する方法だとだめなのかが分かりません。どなたかご教授お願いします。
イメージ説明

調査して分かったこと

  1. 「TextOut()」を使用するのではなく,「TextRect()」を使用し,クリッピング範囲に文字列を出力すれば「" "(半角)を9つ」でも問題なかった(ソースコードのOK1)。
  2. 「TextOut()」を使用するのではなく,「FillRect()」を使用し,キャンバス上の指定四角形を塗りつぶせば問題なかった(ソースコードのOK2)。

ソース

Unit1.cpp

C++

1//--------------------------------------------------------------------------- 2 3#include <vcl.h> 4#pragma hdrstop 5 6#include "Unit1.h" 7//--------------------------------------------------------------------------- 8#pragma package(smart_init) 9#pragma resource "*.dfm" 10TForm1 *Form1; 11//--------------------------------------------------------------------------- 12__fastcall TForm1::TForm1(TComponent* Owner) 13 : TForm(Owner) 14{ 15} 16//--------------------------------------------------------------------------- 17void __fastcall TForm1::Button1Click(TObject *Sender) 18{ 19// TLogFont logfont; 20 LOGFONT logfont; 21 22 // 文字に依存した操作 23 logfont.lfCharSet = DEFAULT_CHARSET; 24 // 文字のクリッピング 25 logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; 26 // 文字を出力する角度(角度×10倍) 27 logfont.lfEscapement = 900; 28 // フォント名 29 StrCopy((char *)logfont.lfFaceName, (const char *)"@MS ゴシック"); 30 // 文字の高さ 31 logfont.lfHeight = 16; 32 // イタリック体指定 33 logfont.lfItalic = false; 34 // 文字を出力する際の基準線(lfEscapementと同じ値) 35 logfont.lfOrientation = 900; 36 // 出力の形式 37 logfont.lfOutPrecision = OUT_DEFAULT_PRECIS; 38 // 出力の間隔 39 logfont.lfPitchAndFamily = DEFAULT_PITCH; 40 // 出力の品質 41 logfont.lfQuality = DEFAULT_QUALITY; 42 // 打消し線の指定 43 logfont.lfStrikeOut = false; 44 // 下線の指定 45 logfont.lfUnderline = false; 46 // 文字の太さ 47 logfont.lfWidth = 700; 48 // 文字の幅 49 logfont.lfWidth = 8; 50 51 Image1->Canvas->Font->Handle = CreateFontIndirect(&logfont); 52 Image1->Canvas->TextOut(10, 85, "23:59:59"); 53// UnicodeString str = _T("23:59:59"); 54// Image1->Canvas->TextOut(10, 85, str); 55} 56//--------------------------------------------------------------------------- 57void __fastcall TForm1::Button2Click(TObject *Sender) 58{ 59 // NG 60 Image1->Canvas->TextOutW(10, 85, " "); 61 // お試し 62// UnicodeString str = _T(" "); 63// Image1->Canvas->TextOutW(10, 85, str); 64/* 65 // OK1 66 Image1->Canvas->TextRect(Rect(10, 7, 25, 85), 67 10, 7, 68 " "); 69 70 // OK2 71 Image1->Canvas->FillRect(Rect(10, 7, 25, 85)); 72*/ 73} 74//--------------------------------------------------------------------------- 75

Unit1.h

C++

1//--------------------------------------------------------------------------- 2 3#ifndef Unit1H 4#define Unit1H 5//--------------------------------------------------------------------------- 6#include <System.Classes.hpp> 7#include <Vcl.Controls.hpp> 8#include <Vcl.StdCtrls.hpp> 9#include <Vcl.Forms.hpp> 10#include <Vcl.ExtCtrls.hpp> 11//--------------------------------------------------------------------------- 12class TForm1 : public TForm 13{ 14__published: // IDE で管理されるコンポーネント 15 TImage *Image1; 16 TButton *Button1; 17 TButton *Button2; 18 void __fastcall Button1Click(TObject *Sender); 19 void __fastcall Button2Click(TObject *Sender); 20private: // ユーザー宣言 21public: // ユーザー宣言 22 __fastcall TForm1(TComponent* Owner); 23}; 24//--------------------------------------------------------------------------- 25extern PACKAGE TForm1 *Form1; 26//--------------------------------------------------------------------------- 27#endif

開発環境

OS:Windows64bit
IDE:Embarcadero C++Builder 10.3.3

CHERRY👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cx20

2021/09/21 14:41

質問文にある画面イメージですが、もう少し見やすいものは無いでしょうか? 表示されているフォントが「MS ゴシック」なのか判断が付かない為です。
cx20

2021/09/21 17:13 編集

画面イメージの更新ありがとうございます。 フォントの形からすると「@MS ゴシック」ではなく「@MS Pゴシック」っぽいですね。
dem0nmichik0

2021/09/21 17:17

cx20様,夜遅く回答ありがとうございます。 本当ですか?文字フォントでPがつく字体(プロポーショナルフォント)は等幅フォントではなく,「文字ごとに設定された“幅”に従い、詰めて表示される」から,今回のような事象になるから注意深く,フォント名はチェックしていました。それで「@MS ゴシック」だから問題ないと思っていました。「@MS ゴシック」は縦文字の時は@がつくから問題ないと思っていたのですが,これが間違っているのでしょうか?
cx20

2021/09/21 17:20

フォントの指定は「@MS ゴシック」で合っていると思います。 自分が試したのは VC++ ですが「@MS ゴシック」で固定幅で表示されることを確認しました(回答欄参照)
guest

回答1

0

ベストアンサー

なぜ「TextOut()で" "(半角)を9つ」を描画する方法だとだめなのかが

根本原因は不明ですが、恐らく固定幅フォントが正しく適用されていない為に表示文字幅が短くなっているのだと思います。
以下は VC++ でフォントを変えて試した結果になります。比較の為に文字列の前後に「[ ]」を入れてみました。

実行例

投稿2021/09/21 15:33

cx20

総合スコア4633

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dem0nmichik0

2021/09/21 17:41

cx20様,回答ありがとうございます。 cx20様の指摘のように,「固定幅フォントが正しく適用されていない」というところに注目して調べたら 「lfPitchAndFamily」のパラメータをデフォルト(DEFAULT_PITCH)ではなく,固定幅(FIXED_PITCH)にしたら,うまくいきました。 [LOGFONT](http://chokuto.ifdef.jp/urawaza/struct/LOGFONT.html) 1つ疑問なのが「(デフォルト)ではフォント名に依存した文字幅にならない」ということなのでしょうか?
cx20

2021/09/22 01:46

> 「lfPitchAndFamily」のパラメータをデフォルト(DEFAULT_PITCH)ではなく,固定幅(FIXED_PITCH)にしたら,うまくいきました。 lfPitchAndFamily ですがフォントが見つからなかったときに使用されるパラメータのようです。 > StrCopy((char *)logfont.lfFaceName, (const char *)"@MS ゴシック"); 気になるのはフォント名の設定の方法です。 C++ Builder について詳しくないのですが Unicode ビルドの場合、char* ではなく Unicode 文字で指定する必要があるのでは無いでしょうか?
cx20

2021/09/22 16:11

フォント名の設定ですが、StrCopy() → wcscpy() に変えて試してもらえますか? 変更前)StrCopy((char *)logfont.lfFaceName, (const char *)"@MS ゴシック"); 変更後)wcscpy(logfont.lfFaceName, L"@MS ゴシック"); <参考> ■ E2034 'wchar t *' 型は 'const char *' 型に変換できないコンパイルエラーの対処方法 https://docwiki.embarcadero.com/Support/ja/E2034_%27wchar_t_*%27_%E5%9E%8B%E3%81%AF_%27const_char_*%27_%E5%9E%8B%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AE%E5%AF%BE%E5%87%A6%E6%96%B9%E6%B3%95
dem0nmichik0

2021/09/23 23:13

cx20様,回答ありがとうございます。 >フォント名の設定ですが、StrCopy() → wcscpy() に変えて試してもらえますか? >変更前)StrCopy((char *)logfont.lfFaceName, (const char *)"@MS ゴシック"); >変更後)wcscpy(logfont.lfFaceName, L"@MS ゴシック"); 上記を試したところ,「lfPitchAndFamily」のパラメータをデフォルト(DEFAULT_PITCH)ではなく,固定幅(FIXED_PITCH)にせずとも,うまくいきました。 ありがとうございます。参考URLを見ました。アプリはBCB6(Win7)からC++Builder10.3(Win10)に変更しました。そのため,cx20様の考えているように,「wchar_t」(Unicode)でコンパイルしています。 なので,変更後のようにしたら,うまくいきました。試しに参考URLの解決1のようにstrcpy()のまま,AnsiString()でキャストしてうまくいくか試したところ,URLに書いてある通り,Unicode文字は正しくコピーされませんでした。 お忙しい中,いろいろ教えていただきありがとうございました。
cx20

2021/09/24 23:52

解決されたようで何よりです。自分も原因が判明してスッキリしました。 VC++も現在はUnicodeビルドが既定なのでC++Builderも同様なのかなと思った次第です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問