2011年1月8日土曜日

Wordで2バイト文字のチェック

Wordデータを英語環境に持って行くと2バイトフォントが使われている箇所を探せないかという話があったのでいい方法はないかな?

下のサンプルは少々強引だが・・・選択範囲に使用している文字のフォント名を取得してWin32APIを使用してフォントが2バイト(日中韓)フォントかの確認をしています。
当然OSに無いフォントがある場合は正常に動作しません。たぶん・・・。

簡単に説明するとCharacter.Font.Nameが実際に表示されているフォントでCharacter.Font.ASCIIが欧文フォント、Character.Font.NameFarEastが日中韓フォントのどれかになります。
他にもアラビア語用とかも選択できるみたいだがめんどくさいので割愛ということで。

Option Explicit
Private Const LF_FACESIZE       As Long = 32&
Private Const LF_FULLFACESIZE   As Long = 64&

Private Const DEVICE_FONTTYPE   As Long = &H2&
Private Const RASTER_FONTTYPE   As Long = &H1&
Private Const TRUETYPE_FONTTYPE As Long = &H4&

Private Type LOGFONT
    lfHeight As Long
    lfWidth As Long
    lfEscapement As Long
    lfOrientation As Long
    lfWeight As Long
    lfItalic As Byte
    lfUnderline As Byte
    lfStrikeOut As Byte
    lfCharSet As Byte
    lfOutPrecision As Byte
    lfClipPrecision As Byte
    lfQuality As Byte
    lfPitchAndFamily As Byte
    lfFaceName(LF_FACESIZE - 1&) As Byte
End Type

Type NEWTEXTMETRIC
    tmHeight As Long
    tmAscent As Long
    tmDescent As Long
    tmInternalLeading As Long
    tmExternalLeading As Long
    tmAveCharWidth As Long
    tmMaxCharWidth As Long
    tmWeight As Long
    tmOverhang As Long
    tmDigitizedAspectX As Long
    tmDigitizedAspectY As Long
    tmFirstChar As Byte
    tmLastChar As Byte
    tmDefaultChar As Byte
    tmBreakChar As Byte
    tmItalic As Byte
    tmUnderlined As Byte
    tmStruckOut As Byte
    tmPitchAndFamily As Byte
    tmCharSet As Byte
    ntmFlags As Long
    ntmSizeEM As Long
    ntmCellHeight As Long
    ntmAveWidth As Long
End Type

Private Const ANSI_CHARSET        As Byte = 0&
Private Const BALTIC_CHARSET      As Byte = 186&
Private Const CHINESEBIG5_CHARSET As Byte = 136&
Private Const DEFAULT_CHARSET     As Byte = 1&
Private Const EASTEUROPE_CHARSET  As Byte = 238&
Private Const GB2312_CHARSET      As Byte = 134&
Private Const GREEK_CHARSET       As Byte = 161&
Private Const HANGUL_CHARSET      As Byte = 129&
Private Const MAC_CHARSET         As Byte = 77&
Private Const OEM_CHARSET         As Byte = 255&
Private Const RUSSIAN_CHARSET     As Byte = 204&
Private Const SHIFTJIS_CHARSET    As Byte = 128&
Private Const SYMBOL_CHARSET      As Byte = 2&
Private Const TURKISH_CHARSET     As Byte = 162&
Private Const VIETNAMESE_CHARSET  As Byte = 163&

Private IsCJK As Boolean                    ' CJKフォントかの確認

Private Declare Function EnumFontFamiliesEx Lib "gdi32" Alias "EnumFontFamiliesExA" ( _
    ByVal hdc As Long, _
    lpLogFont As LOGFONT, _
    ByVal lpEnumFontProc As Long, _
    ByVal LParam As Long, _
    ByVal dw As Long _
) As Long

Private Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
    Destination As Any, _
    Source As Any, _
    ByVal Length As Long _
)

Private Declare Function GetDC Lib "user32" ( _
    ByVal hwnd As Long _
) As Long

Public Sub CheckFarEastFont()
' フォントが日中韓フォントかの確認
    Dim wd_Selection As Word.Selection
    Dim i As Long
    
    Set wd_Selection = Application.Selection
    
    For i = 1 To wd_Selection.Characters.Count
        With wd_Selection.Characters(i)
            If .Font.Name = .Font.NameFarEast And .Font.Name <> "" Then
                Call FontCheck(.Font)
            End If
        End With
    Next
End Sub

Private Sub FontCheck(wd_Font As Word.Font)
' フォントが日中韓のエンコードを所持しているかの確認
    Dim bytBuf()    As Byte
    Dim udtLogFont  As LOGFONT
    
    bytBuf = StrConv(wd_Font.Name, vbFromUnicode)
    With udtLogFont
        .lfCharSet = DEFAULT_CHARSET
        Call MoveMemory(.lfFaceName(0), bytBuf(0), UBound(bytBuf) + 1&)
        .lfPitchAndFamily = 0&
    End With
    
    IsCJK = False
    Call EnumFontFamiliesEx(GetDC(0), udtLogFont, AddressOf EnumFontFamProc, ByVal 0&, 0)
    If IsCJK Then
        wd_Font.Animation = wdAnimationMarchingRedAnts    ' CJKフォントの場合赤い線のアニメーション
    Else
        wd_Font.Animation = wdAnimationNone
    End If
End Sub

Private Function EnumFontFamProc(lpNLF As LOGFONT, lpNTM As NEWTEXTMETRIC, ByVal FontType As Long, LParam As Long) As Long
    Dim FaceName As String
    
    FaceName = StrConv(lpNLF.lfFaceName, vbUnicode)
    Debug.Print Left$(FaceName, InStr(FaceName, vbNullChar) - 1)    ' フォント名
    EnumFontFamProc = 1
    Select Case lpNLF.lfCharSet
    Case SHIFTJIS_CHARSET, GB2312_CHARSET, CHINESEBIG5_CHARSET, HANGUL_CHARSET:
        IsCJK = True
    End Select
End Function

しかし、Unicodeの時代なのに未だに2バイト文字というのもなんだかなぁ。

2011年1月5日水曜日

今年もいいことがありますように

忙しくて、ずうっと放置プレイだった。
まぁ、今年起きそうなことを予想という名の落書きを。

電子書籍バブルの崩壊

半年以内で起きるだろう・・・たぶん。
正直言って今の作り方ではいたずらに体力を消耗しているだけで何も生み出さないだろう。

この状況に誰もが電子書籍は本当に必要なのだろうかと思うだろう。

だが、ホリエモンが月840円のメルマガを1万人に売っているわけで・・・内容は別としてテキストのみの商品が何人もの人間が苦労して創り上げた電子書籍より売上も制作費の安さが勝っているわけです。
ほかにも同人誌でも1ヶ月で3万ダウンロードの売上を出したサークルもあるわけだから、電子書籍がダメという理由ではないと思う。

まぁ何が言いたいかというとあれこれ複雑な規格つくるよりhtmlやPDFでいいんじゃないという話。重要なのは中身だよ。

Andoroidの増殖

既定路線だろう。
今後もケータイからちょっとしたガジェット、カーナビなんかも。
いや・・・専用カーナビ不要論とかでてくるかも。
ただ、法人向けはWindows Phone 7かなとは思っているが日本でいつ出るのやら。

AppleStoreのブレーキ

アプリの量が膨大になって目的のアプリが見つかりづらいなどの不満が両者から公然と出てくるかも。
特に電子書籍型アプリとか、あと著作者に許諾を得ずに作成されて登録される海賊版アプリ。
何かしらの方策は打つとは思うけど。

Windows7の普及、XPの衰退

XPの販売終了、セキュリティの問題からWindows7に普及が加速するだろう。
問題は金のない中小企業がついていけるかというところ。

html5一色の1年

iPhone、Andoroid、PCとの共通の言語はとなるとJAVAではなく手軽さ、作成のしやすさからhtml5だろう。
そして、なんだかんだいってもInternetExplore 9のリリース。

 

あれこれ、書いてみたが今までのコンテンツのリファイン(焼き直し)という感じが強いかも。
要は声が大きい人が素晴らしいといえばみんな群がるという構造は今年も続くだろうという話。

2010年10月24日日曜日

FDKを使用してアラートの取得2

前回の続き

自作のFDKからマスターページの適用のfcodeを送っても、表示されるアラートを消すことができない。
どうやらnotificationが送られていないのが原因らしい。

結局はhWndを取得してキーコードを送るしかない。

2010年10月6日水曜日

FDKを使用してアラートの取得

FrameMaker Developer's Forumで面白い投稿があったのでメモ。
画像が表示できませんやマスターページを適用しますかといったアラートをFDKで取得し、自動ではいを押すプログラムです。
ここで使用されているFP_ActiveAlertはリファレンスにも載っていない実験的なプロパティみたいです。

#include "fapi.h"
#include "fdetypes.h"
#include "futils.h"

VoidT F_ApiInitialize(IntT init)
{
    if (init == FA_Init_First)
    {
        F_ApiNotification(FA_Note_Alert, True);
        F_ApiBailOut();
    }
}

VoidT F_ApiNotify(IntT notification, F_ObjHandleT docId, StringT filename, IntT iparm)
{
    F_ObjHandleT alertId;
    IntT uniq;

    switch (notification)
    {
    case FA_Note_Alert:
        // Get the id of the alert.
        alertId = F_ApiGetId(0, FV_SessionId, FP_ActiveAlert);
        uniq = F_ApiGetInt(FV_SessionId, alertId, FP_Unique);

        // If the alert is "Cannot display some imported graphics...", supppress it.
        switch(uniq)
        {
        case 40086: //"Cannot display some imported graphics..."
        case 40090: //"Cannot display some imported graphics..."
        case 46001: //Suppress ApplyMasterpages message
            F_ApiReturnValue(FR_YesOperation);
            break ;
        case 0:
            //Unfortunately no ID for "The font information changed..."
            if (F_StrCmp(filename, (StringT)"The font information for your system has changed. This change may affect the format and output of your document(s)."))
                F_ApiReturnValue(FR_YesOperation);
            if (F_StrCmp(filename, (StringT)"Die Schriftinformation für Ihr System hat sich geändert. Diese Änderung kann sich auf Formatierung und Ausgabe Ihrer Dokumente auswirken."))
                F_ApiReturnValue(FR_YesOperation);
            break;
        default:
            break;
        }
        break;

    default:
        break;
    }
    F_ApiBailOut();
}

2010年9月5日日曜日

iTextを使ってPDFの拡大縮小配置

iTextを使ってPDFの縮小、移動などの方法は調べても書かれていそうで意外にもなかったりする。
チュートリアルを見てもアフィン変換を使ってうんぬん・・・と書かれていてさっぱり。(高校の数学で習うらしい)

しかし、JAVAや.netだとそのものずばりのクラスが用意されているので移動、拡大縮小、回転の計算が簡単にできたりします。

次のソースはPDF A4->B5に中央に縮小する例です。(ソースはC#)

using System;
using System.Drawing;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace ConsoleApplication1
{
    class Program
    {
        const float pt2mm = 72f / 25.4f;

        static void Main(string[] args)
        {
            string savePdf = "hogehoge.pdf";
            string loadPdf = "fugafuga.pdf";

            // 新しいPDFファイルの作成
            Document pDoc = new Document(PageSize.A4);
            PdfWriter pw = PdfWriter.GetInstance(pDoc, new System.IO.FileStream(savePdf, System.IO.FileMode.Create));
            pDoc.Open();
            PdfContentByte pcb = pw.DirectContent;
            pDoc.NewPage();

            // 既存PDF読み込む
            PdfReader pr = new PdfReader(loadPdf);
            PdfImportedPage page = pw.GetImportedPage(pr, 1);

            // B5サイズへ縮小
            System.Drawing.Drawing2D.Matrix mtx = new System.Drawing.Drawing2D.Matrix();
            mtx.Scale(0.84f, 0.84f);

            // 用紙中央に移動
            mtx.Translate(14 * pt2mm, 20 * pt2mm, System.Drawing.Drawing2D.MatrixOrder.Append);

            // 新しいPDFに貼り付け
            pcb.AddTemplate(page, mtx);

            pr.Close();
            pDoc.Close();
            pw.Close();
        }
    }
}

JAVAだとAffineTransformという命令を使えばいいらしい。

2010年8月10日火曜日

CS4、CS5の段落コンポーザ名

InDesignは言語ごとにUIから操作できないように機能が隠してあったりします。

スクリプトのオブジェクトを見ればだいたいは分かるのだがString型だとわからない。
しかも、言語に依存してしまうのがどうにかならないものかな。

CS4とCS5で使える段落コンポーザ名のメモです。たぶんあっているはず。

CS4 JCS5 JCS4 ECS5 E
Adobe 欧文段落コンポーザAdobe 欧文段落コンポーザーHL Composer
Adobe 日本語段落コンポーザAdobe 日本語段落コンポーザーHL Composer J
Adobe 欧文単数行コンポーザAdobe 欧文単数行コンポーザーHL Single
Adobe 日本語単数行コンポーザAdobe 日本語単数行コンポーザーHL Single J
Adobe 多言語対応段落コンポーザAdobe 多言語対応段落コンポーザーAdobe World-Ready Paragraph ComposerHL Composer Optyca
Adobe 多言語対応単数行コンポーザAdobe 多言語対応単数行コンポーザーAdobe World-Ready Single-line ComposerHL Single Optyca
Linnaeus コンポーザLinnaeus コンポーザーHL Linnaeus

多言語対応段落~を使用するとRTL組版、タイ語、ヒンディ・・・(ここを見て)などが可能になるそうです。
Linnaeusは情報がないので全く不明です。

2010年8月5日木曜日

段落の行と行数を取得するWordVBA

WordのVBAには段落の行と行数を取得する項目がないみたいなので作ってみた。
先頭行から最終行(Endキー)を選択して、選択範囲を取得するというだけです。
何か問題あったら教えてください。

Dim wd_pgfObj As Word.Paragraph
Dim wd_lineObj As Word.Range
Dim LineCount As Long
Dim LineStart As Long
    
Set wd_pgfObj = Selection.Paragraphs(1)
LineCount = 0
LineStart = wd_pgfObj.Range.Start
Do
    Selection.Start = LineStart
    Selection.End = LineStart
    Call Selection.EndKey(Unit:=wdLine, Extend:=wdExtend)
        
    Set wd_lineObj = Selection.Range
    LineCount = LineCount + 1
        
    If Selection.End = wd_pgfObj.Range.End Then
        Exit Do
    End If
    LineStart = Selection.End
Loop
    
Call MsgBox("選択した行:" & LineCount & "行")