[TIL] [C#/NXOpen] Create Font ComboBox ( GlyphTypeface throws NullReferenceException)

Wendy·2020년 6월 23일
0

학습기록

목록 보기
2/20
post-custom-banner

목표 :

C#/NXOpen으로 NX에서 사용할 Font ComboBox 만들기

NX의 기본 Font ComboBox 재사용?

1. 그대로 재사용

원하는 것은 새로 구성중인 화면에 폰트박스만 가져다 쓸수는 없고
폰트박스가 들어있는 팝업을 띄우는것만 가능하다.

  • 기존 : 폰트목록에서 선택 - 1단계
  • 적용시 : 폰트선택 버튼 > 팝업 내부의 폰트목록에서 선택 > 확인 버튼 - 3단계

===>다른 방법을 더 찾아보기로 했다.

2. ComboBox의 Font 목록을 불러오는 함수 재사용

NXOpen.dll 파일을 디코딩 해서 확인해야 한다.

===>현재 내 수준에서는 다른 방법을 찾는것이 빠를 듯 하다.

C#으로 시스템 Font 가져와 NX에 등록?

1.Use Fonts.SystemFontFamilie

foreach (FontFamily fontFamily in Fonts.SystemFontFamilies) 
{
	//make list for Font ComboBox
} 

NX.WorkPart.Fonts.AddFont(this.FontType, FontCollection.Type.Standard); // some font occurs error!!

Font ComboBox 구성에는 성공했으나,
Font를 NX WorkPart에 등록하는 과정에서 일부 폰트가 '파일을 찾을 수 없다'는 에러를 낸다.
난 분명 시스템에 있는 폰트를 불러온건데????
실제로 NX에서 구성해둔 폰트박스에도 에러가 나는 폰트들은 없다.

C:\Windows\Fonts에서 되는폰트, 안되는 폰트를 비교해보니
폰트 파일을 열었을 때 자기 폰트가 바로 나오는 폰트(대표폰트)는 문제가 없고,
다음버튼으로 이동해야 자기 폰트가 나오는 폰트들이 에러가 났다.
그럼 이것을 어떻게 구분할 것인가?
===> 일단 보류

2. Use File from C:\Windows\Fonts

string path = Environment.GetFolderPath(Environment.SpecialFolder.Fonts);
FileInfo[] fontFiles = new DirectoryInfo(path).GetFiles();
foreach (FileInfo fi in fontFiles)
{
	GlyphTypeface font = new GlyphTypeface(new Uri(fi.FullName));	//some file occurs error!! - NullReferenceException
	FontSelection item = new FontSelection(font);
	fontSelectionSet.Add(item);
}

폰트 폴더에는 탐색기에서는 보이지 않는 많은 파일들이 있었다.
SystemFontFamilies에서 불러올땐 200여개의 폰트가 있었는데
DirectoryInfo.GetFiles를 하니 500여개의 파일이 존재했다.
===> 확장자가 ttc, ttf인 파일만 추리기

또한 new Uri(FileInfo.FullName)에는 문제가 없고, Exist를 체크해도 true가 나오는데
new GlyphTypeface() 안에 넣으면 NullReferenceException를 던지는 케이스가 있었다.

도대체 왜그럴까 한참을 찾았는데....
Windows에서 폰트 변경이 일어났을 때 과거 파일을 삭제하지 않는 정책이 있고
이 때문에 뭔가 존재하지만 존재하지 않는 파일이 된 것이다.
===> 에러를 잡고 다음 폰트로 통과하기

string path = Environment.GetFolderPath(Environment.SpecialFolder.Fonts);
FileInfo[] fontFiles = new DirectoryInfo(path).GetFiles();
foreach (FileInfo fi in fontFiles)
{
	if (fi.Extension.IsEqualNoCase(".ttc") || fi.Extension.IsEqualNoCase(".ttf"))
	{
		try
		{
			GlyphTypeface font = new GlyphTypeface(new Uri(fi.FullName));
			FontSelection item = new FontSelection(font);
			fontSelectionSet.Add(item);
		}
		catch (NullReferenceException)
		{
			//just pass
		}
	}
}

===> 잘 돌아가서 좋았는데, 디버깅 때마다 나오는 에러들이 신경쓰여 더 찾아보기로...

2. SystemFontFamilies > FontFamily > GlyphTypeface > get FontUri > check Exists

int FONT_URL_HEADER = 8;    // count header('file:////') ending point
foreach (FontFamily fontFamily in SystemFontFamilies)
{
	GlyphTypeface glyph;
	fontFamily.GetTypefaces().First().TryGetGlyphTypeface(out glyph); 
	if (glyph != null && new FileInfo(glyph.FontUri.ToString().Substring(FONT_URL_HEADER)).Exists) fonts.Add(new FontSelection(glyph));
}

foreach (FontFamily fontFamily in SystemFontFamilies)
폰트 패밀리들을 불러오는데는 문제가 없었으니 그대로 이용

GlyphTypeface glyph;
fontFamily.GetTypefaces().First().TryGetGlyphTypeface(out glyph);
폰트 패밀리를 GlyphTypeface로 변경

glyph != null
변경이 안되었으면 중단

new FileInfo(glyph.FontUri.ToString().Substring(FONT_URL_HEADER)).Exists
glyph에서 FontUri를 추출한뒤 해당 path에 파일이 존재하는지 확인

  • glyph.FontUri.AbsolutePath >> C:/ WINDOWS / FONTS / 파일명.TTF >> TTF뒤에 #1,#2 등등이 표기되지 않음 >> 결과적으로 이 #1, #2등이 과거 버전을 나타내는 표기였다.
  • glyph.FontUri.ToStriong() >> file:////C:/WINDOWS/FONTS/파일명.TTF#1 >> 파일명 앞에 file://// 이 붙음
  • 최종적으로 사용 - glyph.FontUri.ToString().Substring(FONT_URL_HEADER) >> C:/ WINDOWS / FONTS / 파일명.TTF#1 으로 파일이 존재하는지 확인!!

fonts.Add(new FontSelection(glyph));
FontSelection(내가 만든 클래스)로 객체화해서 list에 담기

===> 완성!!!!

후기

new GlyphTypeface() 생성 시 NullReferenceException
이 부분을 찾기 위해 많이 검색을 했는데,
참고자료가 너무 없어서 제2외국어 페이지까지 읽어봣다.
Windows에서 폰트 변경 시 과거 파일을 삭제하지 않는게 원인이라는 것은 알겠는데
그래서 잔여 폰트를 지운다는 해결책은 나에게 맞지 않았다.
이걸 어떻게 해결하는지 찾는데 너무 고생했어서 ㅜㅜ 나서 글을 남기게 되었다.

참고 :
http://pdfandfont.blogspot.com/2016/10/glyphtypeface-new-nullreferenceexception.html
http://itouhiro.hatenablog.com/entries/2012/06/03

profile
개발 공부중!
post-custom-banner

0개의 댓글