Top > OOobbs > 51

OOobbs/51 Edit

  • サマリ: Writer で DrawPage 上のオブジェクトの.FrameRect プロパティと .Position プロパティの値の違い
  • 環境: Writer
  • 状態: 解決
  • 投稿者: 河井?
  • 投稿日: 2005-02-27 (日) 17:44:04

質問 Edit

DrawPage 上のオブジェクトの位置及びサイズ情報を取得及び設定する為に .Size / .Position プロパティが利用できますが、.FrameRect プロパティというものもあり、位置とサイズ情報が両方格納される構造体なので利用出来ると便利なのですが、以下のコードを Writer で実行した時だけ異なる値を示します。

Writer でのみ、.FrameRectの示す値が異なるソース

REM **************************************************
REM *** Draw/Impress/Calc/Writer で、選択された DrawPage 上
REM *** のオブジェクトの位置情報を比較するサンプル
REM *** -- OpenOffice 1.9m79 以降への対応化 --
REM **************************************************
Sub CheckRect
Dim Doc As Object
Dim Page As Object
Dim Shapes As Object
Dim Group As Object
Dim objfX As Double, objfY As Double, objfW As Double, objfH  As Double
Dim objX As Double, objY As Double, objW As Double, objH As Double
	Doc = StarDesktop.CurrentComponent
	Page = GetDrawPageAllways(Doc)
'-- Debug tool としてXray 使用していない時はコメント化
'		Globalscope.BasicLibraries.LoadLibrary( "Xray" )
'		Xray.Xray Page
	Shapes = Doc.getCurrentSelection()
	if IsNull(Shapes) then
		MsgBox "選択されたオブジェクトはありません。"
	elseif Not HasUnoInterfaces(Shapes, "com.sun.star.drawing.XShapes") then		'--> 1.9m79 での挙動に対応
		MsgBox "選択されたオブジェクトは、サイズ情報取得対象ではありません。"
	else
		if Shapes.Count = 1 then			 '--> 1つの時はグループ化しない。(主として Writer への対応措置)
			Group = Shapes.getByIndex(0)
		else
			' 選択されたオブジェクトをグループ化
			Group = Page.group(Shapes)
		end if
		' 選択されたオブジェクトの情報表示
		objW = Group.Size.Width / 100 : objH = Group.Size.Height / 100
		objfW = Group.FrameRect.Width / 100 : objfH = Group.FrameRect.Height / 100
		if IsDrawOrImpress(Doc) then
			objX = (Group.Position.X - Page.BorderLeft) / 100 : objY = (Group.Position.Y - Page.BorderTop)/ 100
			objfX = (Group.FrameRect.X - Page.BorderLeft)  / 100 : objfY = (Group.FrameRect.Y - Page.BorderTop) / 100
		else
			objX = Group.Position.X / 100 : objY = Group.Position.Y / 100
			objfX = Group.FrameRect.X / 100 : objfY = Group.FrameRect.Y / 100
		end if
		
		MsgBox "【選択された DrawPage 上のオブジェクトについて】" & chr$(13) & _
					"-- Size 及び Position プロパティによる取得値 --" & chr$(13) & _
					"幅:" & objW & "mm 高さ:" & objH & "mm" & chr$(13) & _
					"X座標:" & objX & "mm Y座標:" & objY & "mm" & chr$(13) & _
					"-- FrameRect プロパティによる取得値 --" & chr$(13) & _
					"幅:" & objfW & "mm 高さ:" & objfH & "mm" & chr$(13) & _
					"X座標:" & objfX & "mm Y座標:" & objfY & "mm"
		if Shapes.Count > 1 then			'--> 1つ以上の時はグループ化しているので、
			' 選択されたオブジェクトをグループ解除
			Page.ungroup(Group)
		end if
	end if
End Sub

Sub IsWriter(oDocument As Object) As Boolean
	IsWriter = oDocument.supportsService("com.sun.star.text.TextDocument")
End Sub

Sub IsDrawOrImpress(oDocument As Object) As Boolean
	if oDocument.supportsService("com.sun.star.drawing.DrawingDocument") or _
	 oDocument.supportsService("com.sun.star.presentation.PresentationDocument")  then
		IsDrawOrImpress = True
	else
		IsDrawOrImpress = False
	end if
End Sub

Sub GetDrawPageAllways(oDocument As Object) As Object
	'-- Draw or Impress
	if oDocument.supportsService("com.sun.star.drawing.DrawingDocument") or _
		oDocument.supportsService("com.sun.star.presentation.PresentationDocument") then
		GetDrawPageAllways = oDocument.CurrentController.getCurrentPage()
		Exit Sub
	'-- Calc
	elseif oDocument.supportsService("com.sun.star.sheet.SpreadsheetDocument") then
		GetDrawPageAllways = oDocument.CurrentController.ActiveSheet.getDrawPage()
		Exit Sub
	'-- Writer
	elseif oDocument.supportsService("com.sun.star.text.TextDocument") then
		GetDrawPageAllways = oDocument.CurrentController.Model.getDrawPage()
		Exit Sub
	'-- other, DB?
	else
		
	end if
End Sub


Draw 及び Impress では、DrawPage オブジェクトからページ余白情報(.BorderTop や .BorderLeft)を取得することが可能ですが、Calc / Writer のDrawPage オブジェクトからはそれらは、取得することが出来ません。

Doc.CurrentController.Model.PagePrintSettings


が怪しいと思っていますが、ページ余白と比べても上、左共に更に各々 10.02 mm の差があります。Writer の場合のみ描画領域の左上を原点にとっている様に思われますが、具体的な規則性なり根拠が得られないと利用できないのが現状です。
 良い対処方法があれば、宜しくお願いします。

回答 Edit

  • いくつか分かった点があります。

Draw で .TopBorder などが DrawPage から取得できるのは,Draw ではページのスタイルが存在しないことが理由のようです。

Draw と Impress はプレゼンテーション以外の部分はほぼ同じものと思ってください。

Writer および Calc ではページの設定をページスタイルで行います。そのため,ドローページに個別にページの設定を行うプロパティーはありません。

PagePrintSettings に関しては Developer's Guide 7.2 Printing Multiple Pages on one Page に記述がありました。印刷する一枚のページに複数のページをまとめて印刷するときに使用されるもののようです。なので,シェープを取り扱う上では関係ないようです。

あまり関係ないのですが,

Doc.CurrentController.Model.PagePrintSettings

に関して,

Doc.CurrentController.Model

として取得したオブジェクトは

Doc = StarDesktop.CurrentComponent

でドキュメントオブジェクトを取得できたときと同じものになっているはずです。インターフェースが同じです。

  • はにゃ?? 2005-02-27 (日) 20:30:15
  • Calc でのページ設定については OOoBasic/Calc/pagesettings のページで取り上げています。Writer のページスタイルの,ページごとの設定の取得に関しては試したことがないので調べてみます。 -- はにゃ?? 2005-02-27 (日) 20:41:37
  • FrameRect プロパティーはご指摘のとおり描写領域の端からの座標になっているようです。この,描写領域の端からの距離というのは,Y 方向の時には 2 ページ目や 3 ページ目になると非常に大きくなります。

残念ながら Writer の FrameRect は位置の取得のためには使うことができないようです。Position や Size プロパティーをお勧めします。Developer's Guide には記述はありませんでした。IDL Reference には載っていましたが。

Writer での場合は,シェープのアンカーが絡んでくるために位置はかなり複雑になってきます。アンカーはいくつも種類があります。同じシェープのアンカーを「段落」から「ページ」へ変更するだけで Y 座標が変わってきます。

そのため,位置の表示というのが他のドキュメント形式と同じように取り扱っていいのか疑問です。(まあ,そこのところはマクロを書く人それぞれでしょうが)

  • はにゃ?? 2005-02-27 (日) 22:27:42
  • Writer でシェープが選択状態でも,次のコードを使えば選択状態のシェープのページスタイルが取得できるようです。
Sub Main
Dim oDoc As Object
Dim oController As Object
Dim oViewCursor As Object
  oDoc = ThisComponent
  oController = oDoc.getCurrentController()
  oViewCursor = oController.ViewCursor()
  MsgBox oViewCursor.PageStyleName
End Sub

しかし,シェープのページに対する絶対的な位置の取得が Writer では難しいようなのでページスタイルを取得できても意味が ...

  • はにゃ?? 2005-02-27 (日) 23:05:59
  • 短時間に詳細に調べていただきありがとうございます。Writer では、アンカーで結び付けられた対象により原点が異なるのですね。FrameRectを利用したかったのは、コード内で2行書かなくてもいい利便性だけですので、FrameRectから位置情報を得る為にはアンカーに対応する記述を書く必要があるとなると逆に複雑になりますね。ReSizePlusは、OpenOffice.org に元々あるメニューから選択できるコマンド「位置とサイズ」を置き換えるのではなく、足りない機能を補完する目的で作成していますので、座標は本来の「位置とサイズ」で得られる値と同じであればよく、ページ上の絶対位置を求める必要もありません。アンカーの変更は、本来の「位置とサイズ」に任せても良いのかもしれませんし。素直にPosition、Sizeを使いますね。ありがとうございました。 -- 河井? 2005-02-28 (月) 10:32:29
  • 回転を伴う処理を書いたおかげで、.FrameRectと、.Position .Size プロパティの関係が見えてきました。適当な大きさの直方体を描き、30度回転させた後にそのオブジェクトを選択したまま、上記マクロを実行して下さい。注目すべきは、.FrameRectのもつ座標と図形のサイズ両方ともが .Position .Size と異なっていることです。この状態で「制御点の編集」を選択すると図形の制御点の中でひときわ大きい制御点がありますが、そこがどうやら .Positionの示す座標のようです。.Sizeが示す値は、回転を伴わない状態での元々の図形のサイズを示していると思われます。一度回転させてしまった図形の座標を左上端を基準に設定しようとする場合、.FrameRectへのアクセスは必須なのかもしれません。拡大縮小についてもユーザーにとっては、図形が回転されているかどうかは関係なく現在の状態に対して縦横を指定したいと考えると・・・。 -- 河井? 2005-03-04 (金) 13:57:35
  • 意気消沈しておりましたが、Writer上でXray 動かしながらシェーププロパティを眺めていたら、いいものが見つかりました。.AnchorPosition プロパティです。シェープのアンカー位置を絶対座標で表すもののようです。上記の情報表示のif〜elseの間の箇所に以下のようなコードを追加してみました。
elseif IsWriter(Doc) then
  objX = Group.Position.X / 100 : objY = Group.Position.Y / 100
  objfX = (Group.FrameRect.X - Group.AnchorPosition.X) / 100
  objfY = (Group.FrameRect.Y - Group.AnchorPosition.Y) / 100

座標は、望んでいた「位置とサイズ」が示す座標を示すようになりました。

シェープ座標関連で判ったこと
.FrameRectドローページ上のシェープの座標とサイズを示します。(≠絶対座標)
.Positionドローページ上のシェープの基点座標を示します。(≠絶対座標)
.Sizeドローページ上のシェープの回転角度0度時点のサイズを示します。
.AnchorPositionWriter上でのドローページ上のシェープの持つアンカーの座標を示します。(≠絶対座標)

個々のプロパティが絶対座標かどうかは、Draw/Calc/Writerで異なるので、詳細な挙動はアプリ別に分けて書く必要があると思います。「はにゃ」さん、旨くまとめてやってください。-- 河井? 2005-03-04 (金) 15:47:39

  • 上記ソースでは、サイズ(objw/objh)が追加の対策処理にもれてます。まぁ、Xray.Xray Group を適当な箇所に挿入して上記プロパティを見れば、確実ですのでそちらでも確認を! -- 河井? 2005-03-04 (金) 16:48:44
  • AnchorPositoin プロパティーはあることは知っていたのですが,IDL Reference に記載がなかったので推奨されないプロパティーではないかと思っていました。Xray は便利なツールですが (使ったことはありません),プロパティーやメソッドを見逃しがちです。私が作成した DbgInfo2sheet であれば自分でコメントを追加してドキュメントを作成したりすることが簡単です。OOoBasic/Calc/obj? などのオブジェクトのリストはそのファイルを変換して作成しています。 -- はにゃ?? 2005-03-05 (土) 01:00:51


Reload   New Lower page making Edit Freeze Diff Upload Copy Rename   Front page List of pages Search Recent changes Backup   Help   RSS of recent changes