Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Window テキストをCNativeT で取得/設定するユーティリティ関数を追加 #776

Merged
1 change: 1 addition & 0 deletions sakura_core/apiwrap/StdApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#else
#include <ImageHlp.h> //MakeSureDirectoryPathExists
#endif
#include "mem/CNativeT.h"

//デバッグ用。
//VistaだとExtTextOutの結果が即反映されない。この関数を用いると即反映されるので、
Expand Down
75 changes: 75 additions & 0 deletions sakura_core/apiwrap/StdControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ UNICODE版では問題無いが、ANSI版では設定の前にコード変換す
そういった意味でも、このファイル内のラップ関数を使うことを推奨する。
*/

#include <windows.h>
#include <Commctrl.h>
#include "mem/CNativeW.h"
#include "../util/tchar_convert.h"
#include <vector>

Expand All @@ -58,6 +61,78 @@ namespace ApiWrap{
#endif
berryzplus marked this conversation as resolved.
Show resolved Hide resolved
}

/*!
@brief Window テキストを設定する
@param[in] hwnd ウィンドウハンドル
@param[in] str ウィンドウテキスト
*/
inline BOOL Wnd_SetText(HWND hwnd, const CNativeT& str)
{
return SetWindowText(hwnd, str.GetStringPtr());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このコメントは修正要求じゃないです。

CNativeW::operator LPCWSTR( void ) const を追加する選択もあると思います。

この関数の追加と両立できないわけではありませんが、変換演算子を定義すれば他の用途でも GetStringPtr() しなくて済むようになります。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

暗黙の型変換演算子でしょうか?それとも explicit を付けた明示的な型変換演算子でしょうか?
std::basic_stringc_str メソッド経由じゃないと内部データのアドレス取れないようにしてるのでカプセル化を考えたら暗黙にはしない方が良いと思います。そんなの関係ねぇと言ってローレベルな記述をして処理効率を上げるのもそれはそれで乙なものだと思いますが…。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

意図してるのは暗黙のほうです。
シグニチャ通り、constな内部ポインタを返すconst暗黙変換演算子があると便利かな、です。

マズい場合もありえることを初めて知りました...orz

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この提案は完全にNGでした。

むしろ、既存コードにあるimplicit なwchar_t*変換演算子をexplicitに変えた方がいいくらいでした。

X64対応の障害になっちゃうから:smile:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

昔懐かし CString だと暗黙的な型変換があってお手軽だった気がします。
しかし暗黙的な型変換は不具合に繋がりやすいのか何やら敵視されているっぽいです。
面倒くさいからといってバケツでウラン溶液を扱ってはいけないという事でしょうか?

}

/*!
@brief Window テキストを取得する
@param[in] hwnd ウィンドウハンドル
@param[out] str ウィンドウテキスト
@return 成功した場合 true
@return 失敗した場合 false
*/
inline bool Wnd_GetText(HWND hwnd, CNativeT& str)
{
// バッファをクリアしておく
str.Clear();
berryzplus marked this conversation as resolved.
Show resolved Hide resolved

// GetWindowTextLength() はウィンドウテキスト取得に必要なバッファサイズを返す。
// 条件によっては必要なサイズより大きな値を返すことがある模様
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowtextlengtha
const int length = ::GetWindowTextLength(hwnd);
if (length < 0)
{
// ドキュメントには失敗した場合、あるいはテキストが空の場合には 0 を返すとある。
// 0 の場合はエラーかどうか判断できないのでテキストの取得処理を続行する。
// 仕様上は負の場合はありえないが、念の為エラーチェックしておく。
return false;
}

// ドキュメントには NULL 文字に関して言及がないので念の為 +1 しておく
const int bufsize = length + 1;
berryzplus marked this conversation as resolved.
Show resolved Hide resolved

// ウィンドウタイトルを設定するのに必要なバッファを確保する
if (str.capacity() < bufsize)
{
str.AllocStringBuffer(bufsize);
}

int actualCount = ::GetWindowText(hwnd, str.GetStringPtr(), str.capacity());
if (actualCount < 0)
{
// 仕様上は負の場合はありえないが、念の為エラーチェックしておく。
return false;
}
else if (actualCount == 0)
{
// GetWindowText はエラーの場合、またはテキストが空の場合は 0 を返す
if (GetLastError() != 0)
berryzplus marked this conversation as resolved.
Show resolved Hide resolved
{
return false;
}
}
else if(actualCount >= str.capacity())
{
// GetWindowText() の仕様上はありえないはず
return false;
}

// Win32 API の GetWindowText() を呼んだだけでは CNativeT 内部の
// データサイズが更新されないのでデータサイズを反映する
str._SetStringLength(actualCount);

// 正しく設定されているはず
assert(str.GetStringLength() == actualCount);
berryzplus marked this conversation as resolved.
Show resolved Hide resolved
return true;
}

// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
// コンボボックス //
// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
Expand Down
34 changes: 34 additions & 0 deletions tests/unittests/test-StdControl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*! @file */
/*
Copyright (C) 2018-2019 Sakura Editor Organization

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented;
you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment
in the product documentation would be appreciated but is
not required.

2. Altered source versions must be plainly marked as such,
and must not be misrepresented as being the original software.

3. This notice may not be removed or altered from any source
distribution.
*/
#include <gtest/gtest.h>
#include "apiwrap/StdControl.h"

/*!
*/
TEST(StdControl, Wnd_GetText)
{
CNativeT tempText;
EXPECT_EQ(Wnd_GetText(NULL, tempText), false);
berryzplus marked this conversation as resolved.
Show resolved Hide resolved
}