「Win32/64技術 004 文字列グローバル変数にHGLOBALを使う一例」の版間の差分
(ページの作成:「Win32/64_アプリケーション開発に戻る。 前の記事:Win32/64技術 003 ワイド文字列→マルチバイト文字列変換 次の記事:Win32/64技術 005 == '''概要''' == グローバル変数の文字列変数を扱う手法についての記事です。文字列を格納するにはそれなりに容量が必要になってきます。使わない領域になるかもし…」) |
編集の要約なし |
||
3行目: | 3行目: | ||
前の記事:[[Win32/64技術 003 ワイド文字列→マルチバイト文字列変換]] | 前の記事:[[Win32/64技術 003 ワイド文字列→マルチバイト文字列変換]] | ||
次の記事:[[Win32/64技術 005]] | 次の記事:<nowiki>[[Win32/64技術 005]]</nowiki> | ||
== '''概要''' == | == '''概要''' == | ||
129行目: | 129行目: | ||
前の記事:[[Win32/64技術 003 ワイド文字列→マルチバイト文字列変換]] | 前の記事:[[Win32/64技術 003 ワイド文字列→マルチバイト文字列変換]] | ||
次の記事:[[Win32/64技術 005]] | 次の記事:<nowiki>[[Win32/64技術 005]]</nowiki> | ||
[[Win32/64_アプリケーション開発#処理技術|Win32/64_アプリケーション開発]]に戻る。 | [[Win32/64_アプリケーション開発#処理技術|Win32/64_アプリケーション開発]]に戻る。 | ||
2023年11月8日 (水) 19:16時点における版
前の記事:Win32/64技術 003 ワイド文字列→マルチバイト文字列変換
次の記事:[[Win32/64技術 005]]
概要
グローバル変数の文字列変数を扱う手法についての記事です。文字列を格納するにはそれなりに容量が必要になってきます。使わない領域になるかもしれない文字列のためにゆとりをもってグローバル変数としてメモリを確保をするのは気が引けるものです。必要な時に必要なだけの文字数の領域を確保するようにしましょう。
グローバル変数専用のヘッダファイルを作りましょう。利用用途をカテゴリごとに分類しておくと名前の重複が少なくなったりします。ここでは「global.h」とします。どのプログラムファイルからも参照できる変数として使うためにはヘッダファイル化しておくのが大事になります。例えばHGLOBAL型のHGLOBALstringという変数名をグローバル変数にするには以下のように設定します。
File:global.h
#pragma once
#ifndef __GLOBAL__
#define __GLOBAL__
//宣言する型名についての情報が含まれるヘッダファイルの読み込みは必要。
#include <Windows.h>
extern HGLOBAL HGLOBALwstring;;
extern HGLOBAL HGLOBALstring;;
#endif
グローバル変数として定義しますが、ヘッダファイル内では、externキーワードを付けたものを宣言します。これは、関数でいうところのプロトタイプ宣言みたいなものになります。実体はここにありません。実体は各プログラムファイルの中のどこかで一度だけ宣言するとよいことになります。例えばmain.cppでは以下のように記述します。
file:main.cpp
#include <Windows.h>
#include "global.h"
HGLOBAL HGLOBALwstring;
HGLOBAL HGLOBALstring;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInst, LPSTR lpszCmdLine, int nCmdShow){
wchar_t pwchString[] = L"グローバル変数に格納される文字列データ";
char pchString[] = "This is global value.";
size_t length = wcslen(pwchString);//19文字
size_t length = strlen(pchString);//21文字
HGLOBALwstring = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (length + 1) * sizeof(wchar_t));
HGLOBALstring = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (length + 1));
//使い始め
wchar_t* pwchGlobalString = (wchar_t*)GlobalLock(HGLOBALwstring);
char* pchGlobalString = (char*)GlobalLock(HGLOBALstring);
//使い終わったら
GlobalUnlock(HGLOBALwstring);
GlobalUnlock(HGLOBALstring);
…
}
と、上記のように使います。HGLOBALwstring = GlobalReAlloc(HGLOBALwstring, (length + 1) * sizeof(wchar_t), GMEM_MOVEABLE);みたいに、文字列を拡張していく処理も実施できます。その後またpwchGlobalString = (wchar_t*)GlobalLock(HGLOBALwstring);にして、結び付ける処理も必要ですし、拡張したあとに文字列をつぎ足す処理をするのにstrcat_s(pwchGlobalString, length + 1, pwchAddString);のようにする必要があります。こういった処理は繰り返すので、独自に文字列操作関数を作ってしまった方が更に楽です。例えば、リテラル文字列をGlobal変数に格納する関数として、以下のようなものが作れるでしょう。
File:GlobalStringFunc.h
#pragma once
#ifndef __GLOBALSTRING__
#define __GLOBALSTRING__
#include <Windows.h>
#include "global.h"
bool AllocateGlobalMemory(wchar_t* str, HGLOBAL& HGLOBALdata);
void FreeGlobalMemory(HGLOBAL& HGLOBALdata);
#endif
File:GlobalStringFunc.cpp
#include <Windows.h>
#include "GlobalStringFunc.h"
#include "global.h"
bool AllocateGlobalMemory(wchar_t* str, HGLOBAL& HGLOBALdata) {
// すでにメモリが確保されている場合、解放
if (HGLOBALdata != nullptr) {
GlobalUnlock(HGLOBALdata);
HGLOBALdata = nullptr;
}
size_t length = wcslen(str);
HGLOBALdata = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (length + 1) * sizeof(wchar_t));
if (HGLOBALdata == nullptr) {
return false;
}
wchar_t* newstr = (wchar_t*)GlobalLock(HGLOBALdata);
if (newstr != nullptr) {
wcscpy_s(newstr, length + 1, str);
GlobalUnlock(HGLOBALdata);
return true;
}
else {
GlobalFree(HGLOBALdata);
HGLOBALdata = nullptr;
return false;
}
}
// グローバルメモリを解放する関数
void FreeGlobalMemory(HGLOBAL& HGLOBALdata) {
if (HGLOBALdata != nullptr) {
GlobalFree(HGLOBALdata);
HGLOBALdata = nullptr;
}
}
何度も同じ処理をしている部分があると感じたものをこのように関数かしていけるとよいでしょう。文字列操作の流派はいろいろあるので、自分からの提案はこのくらいにしておきます。
前の記事:Win32/64技術 003 ワイド文字列→マルチバイト文字列変換
次の記事:[[Win32/64技術 005]]