Expression Encoder 3 SDK를 사용하면 윈도우 환경에서 쉽게 동영상 인코딩과 썸네일 추출을 할 수 있습니다. Expression Encoder를 설치하면 SDK도 동시에 설치가 됩니다. SDK가 설치된 폴더를 보면 도움말과 함께 관련 어셈블리 그리고 샘플을 제공합니다. 샘플을 분석해보면 어렵지 않다는 걸 알수 있습니다.

하지만 배포할 때 두가지 오류가 나더군요. 해결하는데 조금 시간이 걸렸는데 이 삽질을 공유합니다.

1. 64bit 서버 환경에서 발생하는 오류

{"파일이나 어셈블리 'Microsoft.Expression.Encoder, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' 또는 여기에 종속되어 있는 파일이나 어셈블리 중 하나를 로드할 수 없습니다. 지정된 파일을 찾을 수 없습니다.":"Microsoft.Expression.Encoder, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"}

에러는 'Microsoft.Expression.Encoder.dll'을 찾을 수 없다는 얘기입니다. 하지만 해당 어셈블리는 잘 원래 위치에 잘 있죠. 설치할때 글로벌 어셈블리 캐쉬에도 넣어보고 했지만 같은 에러가 발생합니다. 

 Expression Encoder는 64bit 버전이 없습니다. 32bit 버전 뿐이죠. 그렇다고 64bit OS가 설치되어 돌아가는 환경에서 사용할 수 없는 것은 아닙니다. 다만 실행될때 32bit 로 실행하라는 설정만 해주면 됩니다. 아래와 그림과 같이 빌드 Configuration Manager를 열어서 x86으로 고정시켜주고 빌드해서 실행하면 위의 에러를 해결할 수 있습니다.


2. 권한 문제로 발생하는 오류

ErrorSystem.TypeInitializationException: 'Microsoft.Expression.Encoder.SkuManager'의 형식 이니셜라이저에서 예외를 Throw했습니다. ---> System.Security.Principal.IdentityNotMappedException: ID 참조의 일부 또는 전부를 변환할 수 없습니다.
   위치: System.Security.Principal.NTAccount.Translate(IdentityReferenceCollection sourceAccounts, Type targetType, Boolean forceSuccess)
   위치: System.Security.Principal.NTAccount.Translate(Type targetType)
   위치: System.Security.AccessControl.CommonObjectSecurity.ModifyAccess



위의 에러는 좀 처럼 감을 잡을 수 없습니다. SkuManager를 직접적으로 쓴적도 없고 ID를 본적도 없습니다. 한참을 고생한 결과 권한 문제라는 걸 알았습니다. 저는 Windows Service로 개발을 해서 서비스로 설치를 했기 때문에 아래와 같이 서비스를 실행하는 사용자를 권한이 높은 사용자로 변경해서 해결 했습니다.


ASP.NET에 Expression Encoder SDK를 붙여서 사용하시는 개발자들이 많은데요. 그럴 때는 IIS의 Application Pool의 사용권한과 관련이 있습니다. 이건 제가 직접 해보지는 못했는데 아래 그림처럼 Default Application Pool의 사용자 권한이 Network Service로 되어 있습니다. 이 권한과 Expression Encoder SDK를 사용하는 권한를 잘 따져 보면 답이 나오지 않을까 합니다.




WRITTEN BY
ONESTONE

트랙백  0 , 댓글  1개가 달렸습니다.
  1. azaKnope 2016.04.02 09:47
    http://google.com
secret

트위터, 페이스북과 같은 SNS가 유행하면서 제한된 문자수를 극복하기 위해 또는 너무 길어서 지지분해 보이는 URL을 짧고 간결하게 표시하기 위한 짧은 URL(Short URL Service) 서비스가 필수가 되었습니다. 

tinyurl.com, shorl.com, goo.gl 등 짧은 URL 서비스를 제공하는 사이트가 많은데요. 그중에 많이들 쓰시는 bit.ly 서비스를 프로그래밍을 통해서 짧은 URL을 만들어 쓸 수 있습니다. OAuth, REST API, QR Code 등 몇 가지 방법을 제공하는데 그중에 가장 간단한 REST API 를 통해서 짧은 URL을 만드는 방법을 알아보겠습니다. 

준비
1) 먼저 bit.ly 사이트에 접속하셔서 계정을 만듭니다. http://bit.ly/a/sign_up
2) API Key를 받습니다.  http://bit.ly/a/your_api_key 
3) API 문서는 여기에 있어요. http://code.google.com/p/bitly-api/wiki/ApiDocumentation

요청/응답
1) HTTP GET으로 요청 URL을 만듭니다. 

요청 URL : http://api.bit.ly/v3/shorten 

http://api.bit.ly/v3/shorten?login=아이디&apiKey=API_KEY
&longUrl=긴URL&format=txt

요청 파라미터
 format  json, xml, txt를 지원합니다. 
 longUrl  원본 URL. 긴 URL (URL 인코딩 필요)
 domain   (옵션) bit.ly (기본값)를 쓸것인지? j.mp를 쓸 것인지?
 x_login  (옵션) 계정 만들때 사용한 아이디
 x_apiKey  (옵션) 준비단계에서 받은 API Key 

예)
http://api.bit.ly/v3/shorten?login=bitlyapidemo&apiKey=R_0da49e0a9118ff35f52f629d2d71bf07
&longUrl=http%3A%2F%2Fbetaworks.com%2F&format=json

예제 요청URL처럼 longUrl은 URL인코딩이 필요합니다. 

인증도 없고 HTTP GET으로 요청을 하니 매우 간단하네요. 

2) 응답받기

응답은 3가지 포멧으로 가능합니다. json (jsonp), xml, txt. 필요에 따라서 선택을 하면됩니다. 

JSON응답
{
   
"status_code": 200,
   
"data": {
       
"url": "http://bit.ly/cmeH01",
       
"hash": "cmeH01",
       
"global_hash": "1YKMfY",
       
"long_url": "http://betaworks.com/",
       
"new_hash": 0
   
},
   
"status_txt": "OK"
}

XML 응답
<?xml version="1.0" encoding="UTF-8"?>
<response>
   
<status_code>200</status_code>
   
<status_txt>OK</status_txt>
   
<data>
       
<url>http://bit.ly/cmeH01</url>
       
<hash>cmeH01</hash>
       
<global_hash>1YKMfY</global_hash>
       
<long_url>http://betaworks.com/</long_url>
     
<new_hash>0</new_hash>
   
</data>
</response>
 
txt 응답 
http://bit.ly/cmeH01

샘플코드 (C#)

             private string MakeShorURL(string longurl)

        {

            StringBuilder sb = new StringBuilder();

            //base

            sb.Append(@"http://api.bit.ly/v3/shorten?login=userid&

apiKey=R_xxxxx&format=txt&longUrl=");

            //server page

            sb.Append(Server.UrlEncode(longurl));

 

            // Make Short URL

            WebClient client = new WebClient();

            string shorturl = client.DownloadString(new Uri(sb.ToString()));

 

            return shorturl;

        }


메서드 하나로 짧은 URL을 얻었습니다. 

예제 코드에서는 txt 포멧으로 짧은 URL만 받아서 리턴을 했습니다. 에러처리가 없네요. txt 포멧일 때 에러는 HTTP 상태 코드인 403, 500, 503으로 떨어집니다. WebClient 에러처리 방법으로 하면 되겠습니다.


WRITTEN BY
ONESTONE

트랙백  0 , 댓글  7319개가 달렸습니다.
  1. 이전 댓글 더보기
  2. Have you got a telephone directory? <a href=" http://pybocalide.blog.com/ ">watch prozac nation online megavideo</a> record, Argus will return a reject message indicating this lock-in exists. This applies to
    <a href=" http://oeboraqeti.blog.com/ ">order cheap prozac online</a> Page 18 of 25
    <a href=" http://atebyibeje.blog.com/ ">prozac buy online canada</a> Send completed form to:
    <a href=" http://cidaadaro.blog.com/ ">buy prozac online canada</a> housing is available. The School will pay $5.00/night for student use of AHEC housing. PY4
    <a href=" http://kiucilak.blog.com/ ">get prozac online uk</a> service/volunteer opportunities for students under the supervision of the assigned preceptor. If the
  3. Cool site goodluck :) <a href=" http://haqaorulur.blog.com/ ">online prozac</a> amount dispensed is less than 10% of an original pack and in the reasonable opinion of the
    <a href=" http://qyhehilob.blog.com/ ">prozac online</a> not limited to MOA, ADME, dosage, indications, adverse effects, drug interactions, cost,
    <a href=" http://cidaadaro.blog.com/ ">buy cheap prozac</a> Carolina at Chapel Hill. Affiliation also includes the Doctor of Pharmacy partnership program with
    <a href=" http://ohonubumo.blog.com/ ">buy prozac without rx</a> not want to carry them home, but please do not take any of the house books with you without signing them out.
    <a href=" http://dorybaqyka.blog.com/ ">illegal buy prozac online</a> Change in Provider 49
  4. Your account's overdrawn <a href=" http://jolycesyba.blog.com/ ">buy prozac online uk</a> A. Pathophysiology of common pathophysiology basic principles with with infrequent or depth with no
    <a href=" http://fomycefohum.blog.com/ ">buy prozac online no prescription uk</a> Prescriptions on Hospital and their affiliated Clinics
    <a href=" http://pytidyraq.blog.com/ ">prozac buy online uk</a> The required batch header record is a fixed length record 75 bytes long.
    <a href=" http://aaqopio.blog.com/ ">fluoxetine buy online no prescription</a> The Office of Experiential Training and Continuing Pharmacy Education -TSU COPHS Page 31
    <a href=" http://imusiririka.blog.com/ ">cheap prozac online</a> immunity, you will need to get two doses of the vaccine if you have not already done so, and
  5. How much does the job pay? <a href=" http://www.tnaflix.com/profile/lekorufumobe ">loli underage porn</a> was dat a ring on da blonde one? and wow dis vid is awesome. like one of dose peep said.its one of dose dat u can keep fowardin..
    <a href=" http://www.tnaflix.com/profile/quetetuloyr ">incest loli pics free</a> Brotha has a big dick, but that is one fine hairy ass pussy and she took most of that dick. Love those laides that are wiling to suck ad fuck big black dicks.
  6. How much does the job pay? <a href=" http://www.tnaflix.com/profile/lekorufumobe ">loli underage porn</a> was dat a ring on da blonde one? and wow dis vid is awesome. like one of dose peep said.its one of dose dat u can keep fowardin..
    <a href=" http://www.tnaflix.com/profile/quetetuloyr ">incest loli pics free</a> Brotha has a big dick, but that is one fine hairy ass pussy and she took most of that dick. Love those laides that are wiling to suck ad fuck big black dicks.
  7. How much does the job pay? <a href=" http://www.tnaflix.com/profile/lekorufumobe ">loli underage porn</a> was dat a ring on da blonde one? and wow dis vid is awesome. like one of dose peep said.its one of dose dat u can keep fowardin..
    <a href=" http://www.tnaflix.com/profile/quetetuloyr ">incest loli pics free</a> Brotha has a big dick, but that is one fine hairy ass pussy and she took most of that dick. Love those laides that are wiling to suck ad fuck big black dicks.
  8. How much does the job pay? <a href=" http://www.tnaflix.com/profile/lekorufumobe ">loli underage porn</a> was dat a ring on da blonde one? and wow dis vid is awesome. like one of dose peep said.its one of dose dat u can keep fowardin..
    <a href=" http://www.tnaflix.com/profile/quetetuloyr ">incest loli pics free</a> Brotha has a big dick, but that is one fine hairy ass pussy and she took most of that dick. Love those laides that are wiling to suck ad fuck big black dicks.
  9. I support Manchester United <a href=" http://www.tnaflix.com/profile/eaikajicyhy ">lolit photo sites</a> cabrão do preto tem um ARAMANHO, que é um caralho daquele tamanho !!! LOL never seen a cock so huge, damn..!!
    <a href=" http://www.tnaflix.com/profile/urykoiuna ">loli nymphets list</a> Loves me a dude wit a tongue ring! Got one myself and dudes love it too! Az far az dat dudes dick..... HOTT DAMN!!! Too big fa me but she killed it! I wud b scared but i do love da way dey fucked her!
  10. How would you like the money? <a href=" http://www.tnaflix.com/profile/fomuubuhi ">young lolitta girls</a> I feel bad for her..because if you watch rock of love you'd know she had gotten in a car accident and is covered with scars..that sucks.
    <a href=" http://www.tnaflix.com/profile/lekorufumobe ">free lolitta boy porn</a> The first time I fucked my sister's bf I came a lot.Not till we got out of the bed did I realize how much,He wore condoms and the sheets were fucking soaked from my juices with a huge wet spot in them.His big banana shaped dick sure hit my g spot.
  11. Hello good day <a href=" http://www.tnaflix.com/profile/amiyoru ">passwords loli guestbook</a> definitely schoolgirls that can't suck a dick. open up your mouth and let that fucker down your throat. fucking sexy when he takes it out and puts his cock in the other one's mouth. they can't even take the entire cock in their twats. lame.
    <a href=" http://www.tnaflix.com/profile/lekorufumobe ">preteen pic loli</a> white ass fat pastu dude fuckin a hot chick? think not! shes a whore hes a buyer, its how it works
  12. I'd like a phonecard, please <a href=" http://www.tnaflix.com/profile/qakiydujer ">lolitta foto</a> omfg! they all cum in her ass! I fucking love it. I fucking want it. is it bad that I want to eat her ass after they all cum in it. its a fantasy of mine.
    <a href=" http://www.tnaflix.com/profile/ytuhujobumu ">hentai gratis lolicon</a> I've seen and heard this small dick pig on other vids...Such a sleasy asshole...The only way he can get any is to pay for it...HaHa...
  13. Could you ask him to call me? <a href=" http://www.tnaflix.com/profile/nulygiqebylir ">japan pedo gallery</a> i love a woman with a little cushion for better pushin! wow she would be a great fuck for sure
    <a href=" http://www.tnaflix.com/profile/oqocemyquho ">sexo word pedo</a> Not that it matters cuz it's hot as fuck, but it's still interracial cuz they are different races. Doesn't just have to be black n white.
  14. Some First Class stamps <a href=" http://www.tnaflix.com/profile/ritanakii ">pedophotossex</a> the only good thing i have to say is that the woman is the absolute hottest thing ever on pornhub. she blew me away
    <a href=" http://www.tnaflix.com/profile/ycebytyroot ">pedo angels world</a> good vid... but her left boob looks like its gonna explode or somethings wrong with it.. i hate fake tits like that.. ahhaahaha
  15. Go travelling <a href=" http://www.tnaflix.com/profile/toiceyba ">pedo boy sex sites</a> thats a dude with some slight moding to his body that was a tiny dick with his legs cut open then folded in gross I dont know
    <a href=" http://www.tnaflix.com/profile/nulygiqebylir ">pedo porn movies free</a> Who IS this woman? And is this really just a homevid from a Jamaican vacation??? Hedonism in Jamaica does a toga party every week!
  16. Where's the nearest cash machine? <a href=" http://www.tnaflix.com/profile/nulygiqebylir ">pree teen pedo</a> Pinky loves using that brown strap on, I bet she don't even leave home without it... like a fucking mastercard.
    <a href=" http://www.tnaflix.com/profile/ritanakii ">teenie pedo porn</a> PAHAHAHAHAHAHA I WAS LAUGHING SO FUCKING HARD WHEN HE TOOK THE STETHOSCOPE PART. he doesn't have the other ends in his ears, i think he was distracted by her cleavage.
  17. How much will it cost to send this letter to ? <a href=" http://www.tnaflix.com/profile/oqocemyquho ">lola pedo porno</a> ufffffff kill me this beautiful red and nice girl also i want to fuck her so hard and she is very slim and she has so pretty pussy i like her nice pussy.mmmmmmmmmmmmmm
    <a href=" http://www.tnaflix.com/profile/uosaenaqo ">ilegal pedo picks</a> wow that was terrible acting by her and you see thats why she didnt get much cum in her mouth:S
  18. I'd like to open a business account <a href=" http://www.tnaflix.com/profile/icusemesa ">12yo boy porn</a> Absolutely, Amber. There's an incredible sensuality about the older women. There's a moment when she's kneeling over the younger one and she leans over to kiss her and her right nipple just rests for a moment on her lover's tummy. It almost made me cum. I love the ending, the gentleness of it, the talking softly, the caressing, the easing down from the intensity of cumming. I love the way the older woman lets her fingernails trail along her lover's leg. And, of course, the kisses...the gentle, soft kisses.
    <a href=" http://www.tnaflix.com/profile/inemuobapi ">2 girls showering</a> this was hot. He is actually not bad. i love the way yhe eats pussy and her acting wasn't bad at all
  19. Thanks for calling <a href=" http://www.tnaflix.com/profile/ecaqakoumy ">14yo girl lingerie</a> Tawny kept back for good reason .. amazing blowjob sucking him solid .. dude gets treatment as he watches his cock slide between her perky tits .. Tawny then goes for ride his cock growing harder inside her .. looking adorable as she bends over desk dude amps it up as her twat aches for more .. Tawny begs for harder fucking and he opts for her ass which is so tight he pulls out and cums over her gorgeous face
    <a href=" http://www.tnaflix.com/profile/inemuobapi ">naked girl 12yr</a> i would like to have girl lije this by me, i often wake up in night so horny that i need to cum couple times to sleep again
  20. very best job <a href=" http://www.tnaflix.com/profile/muhudegepeco ">fhm uk may 2010</a> I couldn't take her seriously if she said shit and had an accent like that while she sucked my cock. ...If I had one, that is.
    <a href=" http://www.tnaflix.com/profile/inemuobapi ">sweet 16 sex nude</a> So beautifully intimate. This makes me wonder why I watch all those anal banging movies. This is way more beautiful.
  21. Baltimore Ravens jerseys shop also uses unique optical frames and high quality metals and plastic materials. this part stinks big time! Imagine that you are that person receiving the call and you hear 鎻宔llo, my name is Clare and I鎶?with a company called Financial Solutions International, do you have a few minutes? 6 keyboard shortcuts every nike Baltimore Ravens jerseys user must knowThe great thing about cheap Baltimore Ravens jerseyss is that they can work much faster than you can. As a customer, you really can confound your friends with something different for a get-together, by hiring a cheap Baltimore Ravens jerse nfl jerseys ysal chef to come to your home and give cooking demonstrations.
    [url=http://www.thesis11.com/blog/index.asp?twid=k_1539_nfl16_us-p-tagus2]Mitchell and Ness NFL New York Jets Stitched Snapback Hats - Black[/url]
secret

C# 쓰레드 이야기 중에 저녁식사하는 철학자 문제가 나옵니다. 교착상태(Dead Lock)가 발생하는 상황과 그 해법 중에 하나로 상호배제(Mutual Excrusive)를 설명하는데 꼭 나오는 이야기죠. 교과서에 주로 나오는 문제인데 왠지 해보고 싶어서 직접 코드를 짜보는 Back to the Basic 시간을 가져봤습니다.

식사하는 철학자 문제
5명의 철학자가 원탁에 둘러 앉아 있습니다. 테이블 중앙에는 음식이 있고 철학자의 사이사이에 젓가락이 하나씩 5개가 놓여 있습니다.(사진참조) 철학자들은 생각에 잠기거나 배가 고파지면 먹는 행위 두가지를 할 수 있는데 먹을 때는 반드시 철학자의 양쪽의 젓가락을 모두 사용해야 합니다. 식사를 마치면 젓가락을 내려 놓고 다시 생각에 잠깁니다. 일정시간이 지났을 때 식사를 하지 못하여 굶어 죽는 철학자가 없도록 하려면 어떻게 해야 할까요?


두가지 언어로 작성을 해봤습니다.

C# 코드 (Visual Studio 2010)


C# 즉 .NET Framework 는 쓰레드 동기화 관련된 모니터(lock 키워드)와 뮤텍스(Mutex), 이벤트(AutoResetEvent, ManualResetEvent)들이 잘 만들어져 있어서 쉽게 구현됩니다. Mutex 5개를 사용했습니다.

Java 코드 (JRE 5 이상)



Java 1.4.x 까지는 Sychronized 키워드를 사용하는 모니터와 wait(), notify() 같은 메서드만 제공 되었지만 Java 5부터는 java.util.concurrent 네임스페이스에 쓸만한 그러나 이해를 좀 해야하는 클래스들이 제공이 되네요. 그중에 Semaphore가 들어 있어서 구현을 했습니다.

세마포어와 뮤텍스는 큰차이는 없어 보이는데 구현할 때 명확히 차이가 보입니다. Mutex는 한개 Semaphore는 여러개의 permit을 설정할 수 있습니다.

혹시 숙제하려고 검색해서 들어오신 학생 여러분 그냥 가져가지 말고 스스로 풀어봐야 훌륭한 개발자가 됩니다. 곧 개발자가 귀해지면 훌륭한 개발자들이 많이 필요하니 열공 부탁해요.

WRITTEN BY
ONESTONE

트랙백  0 , 댓글  4개가 달렸습니다.
  1. 비밀댓글입니다
  2. 안녕하세요.
    지금 Os에 식시하는 철학자를 보고 있는 학생인데요
    철학자의 데드럭을 방지하는데 3가지 방법이 있는데 그 중 비대칭 해결방안부분이 이해가 되질 않아 질문드립니다.
    5명의 철학자가 있다는 가정에 홀수 철학자가 왼쪽 젓가락을 먼저 집고 다음 짝수 철학자가 오른쪽 젓가락을 먼저 집는다 라고 책에 나와있습니다.
    그럼 이 부분에 대해서 동시에 홀짝 철학자가
    • 루에나 2012.12.07 14:21
      젓가락을 집으려 한다면 이것 또한 충돌이 일어나지 않을까요??
      그렇담 동시 접근이 일어나지 않게 해야하는데 그럼 결국 비대칭방법의 의미가 쓸모없게 되는데.. 아니면 둘다 동시 접근하는데 우선순위를 두어 홀수 철학자가 먼저 왼쪽 젓가락을 들게하고 내려 놓으면 짝수가 오른쪽 젓가락을 들고
    • 루에나 2012.12.07 14:28
      그래야 동시접근을 제어할 수 있는데.
      이렇게 된다는 가정하에 교착상태는 방지할 수 있지만 한놈이 한 쪽 젓가락을들고 안 놔주면 기아가 발생할 수 있지 않을까요??
      철학자가 밥 먹으려면 양 쪽 젓가락을 모두 사용해야 하니 말이에요
secret

프로그래밍을 하다보면 쓰레드를 사용할 일이 있습니다. 이상한 것은 쓰레드를 써야한다고 생각하면 꼭 MSDN을 다시 보게 된다는 것입니다. 막상 코딩을 하려 하면 막 헷갈려요. 저만 그런가요? 

한빛 미디어 사이트에 C# 쓰레드에 관한 좋은 글이 있어서 소개합니다. 저자는 한동훈님이고 아마 C# 에센스라는 책에 있는 내용이 아닌가 생각됩니다. 작성일이 2001년 11월 인데도 아직도 내용은 살아 있습니다. 초보 개발자나 저처럼 머리가 굳어가서 기억이 가물거리는 개발자들에게 도움이 될 것 같습니다. 


WRITTEN BY
ONESTONE

트랙백  1 , 댓글  0개가 달렸습니다.
secret
트위터의 링크를 타고 들어온 손정의 소프트뱅크 향후 30년 비전 발표 영상을 보고 큰 감동을 얻어 공유 합니다. 
동영상을 만들고 번역까지 해준 하늘달빛님에게 감사 드립니다. 

(동영상 제작 : 하늘달빛 – 트위터, 블로그)

'통섭'이라는 말이 실감 될 정도로 많은 분야의 지식과 진정성이 묻어 있는 진지한 고민을 느낄 수 있었습니다. 과연 손정의 회장이 말하는 30년 후의 모습, 300년 후의 모습이 실현될지... 30년 후의 모습이 그렇다면 나는 어떻게 살아야 하는지 고민을 해봤습니다. 사람을 행복하게 하겠다는 깊은 철학이 소프트뱅크의 30년 후를 빛내 줄 것이라는 확신이 듭니다. 

후반부에 나오는 어린 시절이야기가 너무 절절해서 눈물이 날뻔했어요. 
소프트뱅크와 손정의 회장의 역사를 알고 싶어 졌습니다. 어떤 책이 있는지 추천해주세요. 


WRITTEN BY
ONESTONE

트랙백  1 , 댓글  0개가 달렸습니다.
secret

본 강좌의 원본은 훈스닷넷에 있습니다.

연재 리스트 

  1. Windows 7 멀티터치 시작하기
  2. 미리 정의된 9가지 제스쳐 지원하기 (WM_GESTURE)
  3. 멀티터치 Raw 데이터를 사용 (WM_TOUCH)
  4. Manipulation and Inertia 활용
  5. WPF4 멀티터치 프로그래밍
  6. 실버라이트 4의 멀티터치 프로그래밍

Windows 7이 실버라이트와 결합되면 웹에서도 멀티터치가 가능하도록 만들 수 있다. 물론 Windows 7 운영체제에 종속적이지만 브라우저를 통해서 웹 응용프로그램에서 멀티터치를 경험할 수 있는 길이 열렸습니다. 아래 그림을 살펴보면 멀티터치 입력이 어떤 과정을 통해서 실버라이트 응용프로그램까지 전달 되는지 알 수 있습니다. 윈도우 7의 멀티터치 데이터는 웹 브라우저에 전달이 되고 웹 브라우저는 그 데이터를 다시 실버라이트로 전달하는 구조입니다. 그러므로 웹 브라우저는 인터넷 익스플로러 외에 구글 크롬 등 다른 브라우저에서도 정상적으로 작동 됩니다.


출처 : MSDN

이전 강좌에서는 멀티터치를 윈도우 응용프로그램에 적용하기 위한 여러가지 방법을 소개했습니다. 하지만 실버라이트에서는 한가지 만 지원하는데 바로 Raw Data를 프로그래머에게 던져주는 것이죠. 결국 멀티터치 Raw Data를 가지고 개발자가 여러가지 제스쳐를 만들어야 합니다. 또한 UIElement 개체에 핸들러를 등록하여 처리하는 방식이 아닌 실버라이트 전체 응용프로그램에서 멀티터치 이벤트 핸들러를 등록한다는 것이 마우스와 같은 다른 입력방식과 다른 점입니다.

실버라이트3부터 Touch 라는 클래스가 지원 됩니다. 이 클래스는 FrameReported 라는 이벤트를 제공하는데 이 이벤트가 멀티터치를 처리합니다. 아래 코드와 같이 이벤트 핸들러를 등록하고 Action 값에 따라서 멀티터치의 Down, Move, Up을 처리 할 수 있습니다.

Touch.FrameReported += new TouchFrameEventHandler(Touch_FrameReported);

void Touch_FrameReported(object sender, TouchFrameEventArgs e)

{

foreach (TouchPoint tp in e.GetTouchPoints(_canvas))

{

if (tp.Action == TouchAction.Down) { }

else if (tp.Action == TouchAction.Up) {}

else if (tp.Action == TouchAction.Move) {}

}

}


실버라이트 멀티터치 소스코드 다운로드 : SilverlightMultitouchApplication.zip (Visual Studio 2008, Silverlight 3)


실버라이트의 멀티터치 입력은 기본적으로 '마우스 이벤트 승격'이 적용되는데 이것은 멀티터치 입력의 기본 동작이 마우스클릭으로 사용된다는 의미 입니다. 즉 버튼을 올려놓고 Click 이벤트 핸들러를 등록한 후 멀티터치로 그 버튼을 누르면 Click 이벤트 핸들러가 호출 됩니다. 

"마우스 이벤트 승격"이 특정 시나리오에서는 오히려 방해가 될 수도 있는데 그걸 막을 수 있는 방법을 제공합니다. 바로 TouchFrameEventArgs.SuspendMousePromotionUntilTouchUp() 메서드를 사용하면 됩니다. FrameReported 이벤트 핸들러에서 터치가 Down일때 호출해 주면 Up이 될 때까지 해당 터치에 대해서 "마우스 이벤트 승격"을 하지 않습니다.

이 테스트는 위의 소스코드에서 TouchFrameEventArgs.SuspendMousePromotionUntilTouchUp(); 호출부분을 찾아서 지우고 실행했을 때의 버튼 반응을 비교해 보면 알 수 있습니다. 아래 영상에서도 그 내용을 보실 수 있습니다.



이렇게 실버라이트는 멀티터치 Raw Data를 활용해야 합니다. 결국 프로그래밍을 통해서 제스쳐를 인식하거나 물리적인 시뮬레이션을 구현해야 하는 것이죠. 하지만 잘 찾아보면 참고할 자료들이 있습니다.

http://multitouch.codeplex.com/ 에서는 실버라이트에서 사용할 수있는 Manipulations and Inertia 를 구현한 샘플을 다운로드 받을 수 있습니다. Behavior 로 구현되어 있으니 쉽게 사용할 수있습니다. 라이브 데모를 제공하니 확인을 해보시고 소스코드도 살펴보세요.

WRITTEN BY
ONESTONE

트랙백  0 , 댓글  0개가 달렸습니다.
secret

본 강좌의 원본은 훈스닷넷에 있습니다.

연재 리스트 

  1. Windows 7 멀티터치 시작하기
  2. 미리 정의된 9가지 제스쳐 지원하기 (WM_GESTURE)
  3. 멀티터치 Raw 데이터를 사용 (WM_TOUCH)
  4. Manipulation and Inertia 활용
  5. WPF4 멀티터치 프로그래밍
  6. 실버라이트 4의 멀티터치 프로그래밍


WPF 4가 나오면서 Windows 7의 멀티터치를 적극적으로 지원을 하고 있습니다. 멀티터치를 구현하는 가장 좋은 방법이 바로 WPF 4를 사용하는 것이 아닐까 합니다.

WPF 컨트롤의 상속 구조에서 상위 클래스인 UIElement, UIElement3D, ContentElement 가 멀티터치를 지원 합니다. 즉 WPF에서 사용하는 모든 컨트롤이 멀티터치를 지원 하는 것이죠. 두가지 방식으로 지원을 하는데 첫번째는 멀티터치 원시 데이터(Raw Data)를 지원하고 두번 째는 Manipulation and Inertia를 지원 한다는 것입니다. 그래서 컨트롤의 이벤트를 살펴보면 이런 이벤트가 보입니다.

TouchDown, TouchUp, TouchMove, TouchEnter, TouchLeave


멀티터치 원시 데이터 이용
여러분이 예상하시는 그대로 터치를 하면 TouchDown, 움직이면 TouchMove, 터치를 제거하면 TouchUp 이벤트가 발생합니다. TouchEnter와 TouchLeave가 있는데 터치가 올라가고 내려가는데 반응하는게 아니라 터치를 한 상태에서 터치 영역의 안쪽에서 바깥쪽으로 터치 나가면 TouchLeave 바깥쪽에서 안쪽으로 들어오면 TouchEnter 이벤트가 발생합니다.

마우스와 조금 다른데 생각해보면 터치는 커서가 없기 때문에 공중에 떠서 버튼위에 올라가도 감지할 방법이 없기 때문이겠죠. (이런것들이 모두 터치 인터페이스의 특징입니다.)

그럼 Canvas 하나를 올리고 XAML 에서 위의 이벤트 핸들러를 등록하고 터치가 발생한 지점에 위치와 ID 정보를 표시해 봅시다. XAML 코드에 이렇게 사용되었습니다. 물론 코드 비하인드에서도 이벤트 핸들러를 등록할 수 있습니다.

<Canvas x:Name="_canvas" Canvas.Top="300" Canvas.Left="300"

                TouchDown="Canvas_TouchDown" TouchMove="Canvas_TouchMove" TouchUp="Canvas_TouchUp"

                TouchEnter="_canvas_TouchEnter" TouchLeave="_canvas_TouchLeave"

                Width="500" Height="500" Background="#FF0033FF">


이전 WM_TOUCH, WM_GESTURE 로 프로그래밍 할때는 터치 이벤트가 전체 프로그램에 하나 들어 오는데 WPF 4 에서는 컨트롤 마다 따로 멀티터치 이벤트를 처리 할 수 있습니다.

이벤트 핸들러를 살펴보면 핸들러마다 매개변수로 TouchEventArgs 를 사용합니다. 이 매개변수를 열어보면 TouchDevice, TouchPoint 등 멀티터치 관련된 원시 데이터를 얻을 수 있습니다. 이 데이터를 이용해서 하고 싶은 작업을 하면 되죠.

코드 비하인드에 추가적인 코드를 넣고 실행을 하면 아래 영상처럼 작동을 합니다. WM_TOUCH 샘플과 방식은 약간 다르지만 코드는 매우 비슷하네요.


영상이 보이지 않으면 : http://tvpot.daum.net/my/ClipView.do?ownerid=ADowB8WbINw0&clipid=25744494&q=

WPF 4 멀티터치 Raw data 소스코드 다운로드 : Wpf4MultitouchVisualization.zip (Visual Studio 2010, WPF 4)


WPF 4 멀티터치 Manipulation
WPF 4는 Manipulation 도 내장을 하고 있고 (이전 강좌의 Manipulation은 COM으로 구현된 라이브러리를 Interop 해서 쓰는 방식) 역시 컨트롤 마다 따로 프로그래밍을 할 수 있습니다. 매번 하는 샘플이지만 사진을 가지고 노는 샘플을 만들어 봅시다.

Image 컨트롤에 IsManipulationEnabled 라는 속성이 있고 Manipulation과 Inertia 관련 이벤트들이 존재하는 걸 볼 수 있습니다.

ManipulationStarting, ManipulationStarted, ManipulationDelta, ManipulationBoundaryFeedback, ManipulationCompleted, ManipulationInertiaStarting

이런 이벤트들이 놀랍게도 Image 컨트롤에 추가가 되었습니다. Manipulation의 기본 개념은 이전 강좌를 통해서 살펴봤으니 여기서는 코드만 보고 가겠습니다.

Image 컨트롤의 XAML 코드 입니다.

<Image Source="C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg" Width="100" Height="80"

               IsManipulationEnabled="True"

               ManipulationStarting="Image_ManipulationStarting" ManipulationDelta="Image_ManipulationDelta" ManipulationStarted=""

               ManipulationInertiaStarting="Image_ManipulationInertiaStarting"

               >

            <Image.RenderTransform>

                <MatrixTransform  />

            </Image.RenderTransform>

        </Image>


IsManipulationEnabled="True" 와 함께 이벤트 핸들러를 등록했고 변환을 편하게 적용하기 위해 MatrixTransform을 사용한 다는 걸 알 수 있습니다.

private void Image_ManipulationStarting(object sender, ManipulationStartingEventArgs e)

{

    e.ManipulationContainer = RootCanvas;

 

     e.Mode = ManipulationModes.All;

     //e.Mode = ManipulationModes.Rotate | ManipulationModes.Scale;

}


우선 Manipulation이 시작되는 시점(ManipulationStarting)에 적용될 범위를 정하고 사용할 조작의 종류들을 지정할 수 있습니다.

private void Image_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)

{

  FrameworkElement element = e.Source as FrameworkElement;

 

if (element != null)

{

Matrix matrix = ((MatrixTransform)element.RenderTransform).Matrix;

ManipulationDelta deltaManipulation = e.DeltaManipulation;

 

Point center = new Point(element.ActualWidth / 2, element.ActualHeight / 2);

center = matrix.Transform(center);

 

matrix.ScaleAt(deltaManipulation.Scale.X, deltaManipulation.Scale.Y, center.X, center.Y);

matrix.RotateAt(e.DeltaManipulation.Rotation, center.X, center.Y);

matrix.Translate(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y);

 

((MatrixTransform)element.RenderTransform).Matrix = matrix;

 

 

e.Handled = true;

 

}


이벤트를 발생시킨 소스를 찾아서 변화된 값이 모두 들어 있는 DeltaManipulation 속성에서 값을 찾아 MatrixTransform을 적용 했습니다.

WPF4 멀티터치 Inertia
관성은 ManipulationInertiaStarting 이벤트 핸들러에서 초기 값을 잘 정해주기 만 하면 알아서 잘 적용이 됩니다. 아래 코드를 보세요. 제가 물리/수학을 잘 못해서 가속도 값 계산 다른 샘플에서 가져다 썼습니다.

private void Image_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e)

{

     // (10 inches * 96 DIPS per inch / 1000ms^2)

     e.TranslationBehavior = new InertiaTranslationBehavior()

     {

         InitialVelocity = e.InitialVelocities.LinearVelocity,

         DesiredDeceleration = 1.0 * 96.0 / (1000.0 * 1000.0)

     };

 

     // Decrease the velocity of the Rectangle's resizing by

     // 0.1 inches per second every second.

     // (0.1 inches * 96 DIPS per inch / (1000ms^2)

     e.ExpansionBehavior = new InertiaExpansionBehavior()

     {

         InitialVelocity = e.InitialVelocities.ExpansionVelocity,

         DesiredDeceleration = 0.1 * 96 / 1000.0 * 1000.0

     };

 

     // Decrease the velocity of the Rectangle's rotation rate by

     // 2 rotations per second every second.

     // (2 * 360 degrees / (1000ms^2)

     e.RotationBehavior = new InertiaRotationBehavior()

     {

         InitialVelocity = e.InitialVelocities.AngularVelocity,

         DesiredDeceleration = 720 / (1000.0 * 1000.0)

     };

     e.Handled = true;    

 }


결국 TranslationBehavior , ExpansionBehavior , RotationBehavior 속성을 설정해 주는데 초기 속도와 원하는 가속도를 정해주고 있습니다.

WPF 4 멀티터치 Manipulation  샘플 : Wpf4ImageManipulation.zip (Visual Studio 2010, WPF 4)



실제 실행 결과는 아래 영상을 보세요.


영상이 보이지 않으면 : http://tvpot.daum.net/my/ClipView.do?ownerid=ADowB8WbINw0&clipid=25745220&q=


WPF 4 에서 멀티터치와 잘 통합되어 프로그래밍이 많이 편해진걸 느낄 수 있습니다. 하지만 아직도 멀티터치만이 할 수 있는 인터페이스는 연구해야  할 과제죠.


WRITTEN BY
ONESTONE

트랙백  0 , 댓글  1개가 달렸습니다.
  1. En attendant l'annonce d'un second épisode, http://www.moncleroutletespain.com/ moncler españa, Electronic Arts nous propose, http://www.moncleroutletespain.com/ moncler?? de redecouvrir la version iOS de Mirror's Edge en la proposant gratuitement pendant quelques heures. Cela concerne aussi bien la version iPhone/iPod (100 Mo) que la version iPad (123 Mo), http://www.moncleroutletespain.com/ moncler online. News Robert Downey Jr, http://www.moncleroutletespain.com/ moncler chaquetas. et Gwyneth Paltrow : amitié, http://www.moncleroutletespain.com/ http://www.moncleroutletespain.com/, drogue et alcool News De nouvelles images pour L, http://www.moncleroutletespain.com/ moncler outlet.A. NoireRelated articles:


    http://think1more.kr/222 http://think1more.kr/222

    http://hapina.tistory.com/category/?page=3 http://hapina.tistory.com/category/?page=3
secret


본 강좌의 원본은 훈스닷넷에 있습니다.

연재 리스트 

  1. Windows 7 멀티터치 시작하기
  2. 미리 정의된 9가지 제스쳐 지원하기 (WM_GESTURE)
  3. 멀티터치 Raw 데이터를 사용 (WM_TOUCH)
  4. Manipulation and Inertia 활용
  5. WPF4 멀티터치 프로그래밍
  6. 실버라이트 4의 멀티터치 프로그래밍


조작과 관성이라는 뜻의 Manipulation and Inertia API는 멀티터치 API 중에서 가장 강력한 기능을 가지고 있습니다. 원래는 마이크로소프트 서피스 SDK에 들어 있던 API인데 윈도우 7에 적용이 되었습니다. 사실 이동, 회전, 크기 조절은 모두 수학계산입니다. 관성도 물리 시간에 배우는 몇가지 공식이 적용되는 결국 수학으로 표현됩니다. 간단하지만은 않겠죠. 올바르게 구현하려면 조금  시간이 걸릴 것입니다. 하지만 Manipulation and Inertia API는 내부적으로 이 계산을 알아서 해주고 프로그래머에게는 결과 값만 이벤트로 알려주는 착한일을 합니다. 고맙죠.


Manipulation API
먼저 Manipulation API는 2D 환경에서의 변환 즉, 이동(Translation), 회전(Rotation), 크기조절(Rotation)를 담당합니다. WM_GESTURE 메시지와 다른 것은 모든 변환이 동시에 적용 될 수 있다는 것이다. 이동을 하면서 회전과 크기조절이 동시에 가능하죠. 또한 한 개 또는 두 개의 터치입력에 반응하는 WM_GESTURE와는 달리 여러 개의 멀티터치 입력에도 이동, 회전, 크기변환이 되어 조금 더 자연스러운 느낌을 줄 수 있습니다. .

아래 그림을 살펴보면 Manipulation API가 어떻게 작동되는지 잘 알 수 있습니다. COM으로 구현되어 있는 Manipulation API는 먼저 윈도우 7이 제공하는 WM_TOUCH 메시지의 원시(Raw) 데이터를 입력 받는 Manipulation Processor를 생성합니다. Manipulation Processor는 3가지 이벤트를 발생시키는데 ManipulationStarted 이벤트는 오브젝트를 조작하기 시작할 때 발생하고 ManipulationDelta 이벤트는 이동, 회전, 크기변환이 일어나는 중간에 발생하며 ManipulationCompleted 이벤트는 오브젝트에서 손가락을 떼어 조작을 마무리 하면 발생합니다.

결국 WM_TOUCH Raw data를  활용할 뿐 Application 단에서 모두 처리되는 구조 입니다.



조작이 일어나는 중간에 발생하는 ManipulationDelta 이벤트에서 전달되는 매개변수를 아래 표에서 살펴보세요. 여기서 변화량은 이전 이벤트와 현재 이벤트 사이의 변화량을 말하며 누적량은 ManipulationStarted 이벤트가 발생한 시점부터 현재 이벤트까지 누적된 변화량을 말한다.

종류

속성

설명

변화량

translationDeltaX

X축으로 이동한 변화량

translationDeltaY

Y축으로 이동한 변화량

scaleDelta

크기 변화량(1이 원래크기 1보다 작으면 작아짐)

rotationDelt

회전 변화량 (양수는 시계방향, 음수는 반시계방향)

누적량

cumulativeTranslationX

누적된 X축 이동량

cumulativeTranslationY

누적된 Y축 이동량

cumulativeScale

누적된 크기 변화량

cumulativeRotation

누적된 회전 변화량


즉, 이벤트 핸들러의 매개변수를 통해서 변화된 크기에 대한 정보를 프로그래머에게 알려줍니다. 프로그래머는 그 변화량 또는 누적량을 사용하면 됩니다.

Inertia API
Inertia API를 이용하면 간단한 물리 시뮬레이션을 구현할 수 있습니다. 물리 시뮬레이션은 우리가 실제 환경에서 사물을 이동할 때의 법칙을 멀티터치 응용프로그램에도 적용을 해준다는 것입니다. 예를 들어 책상 위의 물체를 잡고 이리저리 움직이다가 저쪽 끝으로 던지면 그 물체는 관성에 의해서 조금 더 미끄러지며 움직이다가 마찰력에 의해서 멈추게 됩니다. 회전이나 크기 변경도 마찬가지로 관성이 적용될 수 있습니다. 이런 물리적인 움직임을 우리의 멀티터치 응용프로그램에 적용을 하면 매우 자연스러운 느낌을 만들 수 있게 되는데 실제 손가락을 이용하는 터치 인터페이스와 연결되면 NUI(Nature User Interface)라는 말을 실감할 수 있게 만들수 있습니다.

Inertia API는 항상 Manipulation API와 함께 사용하게 된다. 그 이유는 Manipulation API가 끝나는 시점의 속도 등의 값들이 Inertia API의 초기값이 되어 물리적인 시뮬레이션을 시작하기 때문입니다. Inertia Processor가 시작 될 때 입력되는 초기값들의 종류를 아래 표에서 확인 할 수 있습니다. 이 값들을 조작 API의 BeforeInertia 이벤트 핸들어에서 설정을 하게 되면 추가적인 코드 없이도 관성이 적용되어 자연스러운 움직임을 구현할 수 있습니다.

속성

설명

InertiaTimerInterval

관성처리 이벤트가 발생하는 간격

MaxInertiaSteps

발생되는 이벤트의 최대 개수

InitialVelocity

초기 속도 값

DesiredDisplacement

원하는 이동거리

InitialAngularVelocity

초기 회전하는 속도 값

DesiredRotation

원하는 회전 각도 (라디안 값으로 표현)



구현 예
닷넷 환경에서 구현된 코드 조각을 살펴보겠습니다.

using Windows7.Multitouch.Manipulation;

private readonly ManipulationInertiaProcessor processor;

processor = new ManipulationInertiaProcessor

(ProcessorManipulations.ALL, Factory.CreateTimer());

 

processor.ManipulationStarted += processor_ManipulationStarted;

processor.ManipulationDelta += processor_ManipulationDelta;

processor.ManipulationCompleted += processor_ManipulationCompleted;

// WM_TOUCH 데이터(멀티터치 Raw data)를 사용합니다.
_image.StylusDown += new StylusDownEventHandler(Window1_StylusDown);

_image.StylusMove += new StylusEventHandler(Window1_StylusMove);

_image.StylusUp += new StylusEventHandler(Window1_StylusUp);

// WM_TOUCH 데이터를 연결시킵니다.
void Window1_StylusUp(object sender, StylusEventArgs e)

{

   processor.ProcessUp((uint)e.StylusDevice.Id,

e.GetPosition(_canvas).ToDrawingPointF());

}

 

void Window1_StylusMove(object sender, StylusEventArgs e)

{

  processor.ProcessMove((uint)e.StylusDevice.Id,

e.GetPosition(_canvas).ToDrawingPointF());

}

 

void Window1_StylusDown(object sender, StylusDownEventArgs e)

{

   processor.ProcessDown((uint)e.StylusDevice.Id,

e.GetPosition(_canvas).ToDrawingPointF());

}

 

processor.BeforeInertia += processor_BeforeInertia;

void processor_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)

{

_translate.X += e.TranslationDelta.Width;

_translate.Y += e.TranslationDelta.Height;

_rotate.Angle += e.RotationDelta * 180 / Math.PI;

_scale.ScaleX *= e.ScaleDelta;

_scale.ScaleY *= e.ScaleDelta;

}

void processor_BeforeInertia(object sender, BeforeInertiaEventArgs e)

{

processor.InertiaProcessor.InertiaTimerInterval = 15;

processor.InertiaProcessor.MaxInertiaSteps = 500;

//processor.InertiaProcessor.InitialVelocity = … //processor.InertiaProcessor.DesiredDisplacement = …

//processor.InertiaProcessor.InitialAngularVelocity = …

//processor.InertiaProcessor.DesiredRotation = …

//processor.InertiaProcessor.InitialExpansionVelocity = …

//processor.InertiaProcessor.DesiredExpansion = …

}


ManipulationInertiaProcessor라는 클래스를 초기화 하고 ManipulationStarted, ManipulationDelta, ManipulationCompleted 이벤트 핸들러를 등록했습니다. 조작이 끝날때 Inertia를 초기화하면 관성도 적용을 할 수 있습니다.

한가지 더 있습니다. 탄성을 적용할 수 있습니다. 오브젝트를 벽에 던지면 튕겨 나오듯이 모니터의 경계면에 우리가 던지 오브젝트가 튕겨져 나오는 걸 시뮬레이션 할 수 있습니다. 아래처럼 간단한 코드를 넣으면 말이죠.

processor.InertiaProcessor.Boundary = new System.Drawing.RectangleF(1.0f, 1.0f, (float)_canvas.ActualWidth, (float)_canvas.ActualHeight);

processor.InertiaProcessor.ElasticMargin = new System.Drawing.RectangleF(200, 50, 800, 700);


이 코드의 이미는 아래 그림과 같이 관성이 적용될 영역을 지정하고 (Boundary) 관성이 적용될 영역(ElasticMargin)을 지정해 주는 방법 입니다.



Manipulation and Inertia 사용 소스코드 다운로드 : WpfManuplationAndInertia.zip (Visual Studio 2008, .NET Framework 3.5)


실행 결과를 아래 영상으로 확인할 수 있습니다.


WRITTEN BY
ONESTONE

트랙백  0 , 댓글  0개가 달렸습니다.
secret

본 강좌의 원본은 훈스닷넷에 있습니다.

연재 리스트 

  1. Windows 7 멀티터치 시작하기
  2. 미리 정의된 9가지 제스쳐 지원하기 (WM_GESTURE)
  3. 멀티터치 Raw 데이터를 사용 (WM_TOUCH)
  4. Manipulation and Inertia 활용
  5. WPF4 멀티터치 프로그래밍
  6. 실버라이트 4의 멀티터치 프로그래밍

이전 강좌에서 소개된 9개의 미리 정의된 제스쳐는 쉽고 빠른 개발 방법이지만 9개 이외의 다른 제스쳐를 만들어 낼 수는 없습니다. 그래서 새로운 인터페이스를 만들고 싶다면 멀티터치 데이터의 원본(Raw Data)을 이용할 수 있어야 합니다.

마우스를 프로그래밍할 때 생각해보면 마우스의 위치 값, 왼쪽 버튼 클릭, 오른쪽 버튼 클릭 등의 데이터가 있고 MouseDown, MouseMove, MouseUp 이벤트가 있는 것을 기억할 것입니다. 멀티터치도 다르지 않습니다. WP_TOUCH라는 Windows 7 Native 메시지가 비슷한 정보를 우리의 응용프로그램에 전달해 줍니다.

Win32 API에서 WM_TOUCH를 받으려면 먼저 우리가 다루고 있는 윈도우를 WM_TOUCH 메시지 전달이 가능하도록 RegisterTouchWindow() 함수를 이용하여 등록을 하는 과정이 필요합니다. 그러면 터치 입력이 있을 때마다 TOUCHINFO라는 구조체가 매개변수로 전달 되는데 GetTouchInputInfo() 함수를 호출하여 전달된 멀티터치 메시지 데이터를 분석 할 수 있습니다. 하지만 우리는 닷넷 환경에서 작업을 할 것이기 때문에 이런 등록과정은 숨겨져 있습니다.

다만 WP_TOUCH가 전달하는 메세지의 내용을 살펴볼 필요가 있습니다. WM_TOUCH 메시지의 자세한 내용은 MSDN을 참조하세요.

입력 값

설명

ID

여러 개의 터치입력을 구분하는 ID

위치

화면 좌표 (x,y)

Contact의 크기

터치입력의 너비 (cxContact, cyContact)

Primary Contact 인지?

첫 번째 터치입력이면 true

Palm 인지?

손가락 입력이 아니면 true

Time

터치입력 발생 시각



마우스 보다 다양한 내용을 전달하는 걸 볼 수 있고 멀티터치를 구분하기 위해 ID 값이 존재하는 것을 알 수 있습니다. 제가 테스트 한 멀티터치 디바이스에서 ID 값은 처음 터치입력은 ID 10, 두 번째 터치는 11, 세 번째 터치는 12처럼 1씩 증가하면서 부여되고 모든 터치가 제거된 후에 다시 터치 입력을 하면 다시 ID 10부터 시작을 하는 식으로 부여됩니다. 이런식의 ID 변화는 손가락이 현재 몇개가 터치되어 있는지 확인 할 수 있겠죠.

당연히 화면에서의 위치 정보(이것은 마우스의 위치를 정하는 방법과 같습니다)가 있고 터치 입력의 넓이가 있습니다. 또한 첫번째 손가락인지, 손가락이 아니고 손바닥인지를 알 수 도 있습니다.

윈폼(WinForm) 환경에서 터치 데이터 활용
아래 코드처럼 TouchHandler 인스턴스를 생성하고 TouchDown, TouchMove, TouchUp 이벤트 핸들러를 등록합니다. 이벤트 핸들러에서 전달된 매개변수를 열어보면 위의 표에서 설명된 터치 입력에 대한 원시 데이터가 전달된 것을 확인 할 수 있죠. 이 코드는 마우스를 다루는 코드와 같군요. 다만 여러개가 입력될 수도 있다는 걸 제외하면요.

윈폼에서는 Windows7.Multitouch.WinForms.dll 을 사용합니다. 이 어셈블리를 구하는 방법은 이전 강좌에서 확인하세요.

using Windows7.Multitouch;

private TouchHandler _touchHandler;

_touchHandler = Factory.CreateHandler<TouchHandler>(this);

_touchHandler.TouchDown += OnTouchDownHandler;

_touchHandler.TouchMove += OnTouchMoveHandler;

_touchHandler.TouchUp += OnTouchUpHandler;

 

private void OnTouchDownHandler(object sender,TouchEventArgs e)

{

//e.Location

//e.Id

//e.AbsoluteTime

//e.ContactSize

//e.IsPrimaryContact

//e.IsTouchPalm

}

윈폼 샘플 소스코드 : TouchDataVisualization.zip (Visual Studio 2008, WinForm, .NET Framework 3.5)


소스코드는 손가락을 올렸을 때 손가락의 정보를 보여줍니다. 여기에서는 아이디가 10, 100 이런식으로 부여되네요. 아이디 부여 방식은 디바이스 드라이버 마다 다른지 확인을 해봐야겠습니다.


실행 결과를 영상으로 보세요.



동영상이 안보이면 http://tvpot.daum.net/my/ClipView.do?ownerid=ADowB8WbINw0&clipid=25737296&q=

한가지 기억할 것은 WP_TOUCH를 이용하면 WP_GESTURE를 이용할 수 없다는 것입니다. 즉, 터치의 포인트에 대한 정보를 받으면서 동시에 9가지 제스쳐를 다룰 수 없다는 것이죠.

WPF에서 멀티터치 원시 데이터를 이용하는  방법 (.NET Framework 3.5)
WPF에서도 같은 방법으로 프로그래밍을 합니다. WPF에서는 Windows7.Multitouch.WPF.dll을 참조해서 해야죠. 내부적인 방식이 약간 다른데 스타일러스 펜의 입력을 약간 우회하는 방법을 사용하나 봅니다. 소스를 따라 들어가다 보니 아래와 같은 코드가 있던데요. 이것은 아마도 WPF4가 나오기전에 멀티터치 프로그래밍을 위해서 스타일러스 입력을 활용할 수 있도록 열여주는 코드 같습니다.

HwndSource hs = (HwndSource)PresentationSource.FromVisual(this);
SetProp(new HandleRef(this, hs.Handle),     

"MicrosoftTabletPenServiceProperty", new HandleRef(null,    

new IntPtr(0x01000000)));


어째든 우리는 윈폼의 코드와 같은 방식으로 프로그래밍이 가능합니다.

Loaded += (s, e) => { Factory.EnableStylusEvents(this); };

 

StylusDown += OnTouchDownHandler;

StylusMove += OnTouchMoveHandler;

StylusUp += OnTouchUpHandler;


WPF 소스코드 다운로드 : TouchDataVisualization.zip (Visual Studio 2008, .NET 3.5)


실행한 결과는 아래 영상에서 확인 할 수 있습니다. 윈폼의 실행결과와 같습니다.



동영상이 보이지 않으면 : http://tvpot.daum.net/my/ClipView.do?ownerid=ADowB8WbINw0&clipid=25737794&q=

우리는 멀티터치의 원시 데이터(Raw Data)를 얻었습니다. 이 데이터를 가지고 프로그래밍을 하여 다양한 제스쳐를 만들거나 손가락을 그림을 그리는 등의 여러 아이디어 구현에 활용 할 수 있습니다.

이 강좌의 소스는 .NET Framework 3.5 를 사용했지만 WPF 4가 나오면서 조금더 세련되고 쉬운 방법으로 멀티터치를 프로그래밍을 할 수 있습니다. 다음 강좌에서 그 방법을 확인해 보세요.





WRITTEN BY
ONESTONE

트랙백  0 , 댓글  1개가 달렸습니다.
  1. keugbang 2015.09.22 18:59
    마이크로소프트의 링크가 이젠 사라지고 없군요. 하지만 첨부하신 예제 소스파일 덕분에 많은 도움이 되었습니다.
secret

본 강좌의 원본은 훈스닷넷에 있습니다.

연재 리스트 

  1. Windows 7 멀티터치 시작하기
  2. 미리 정의된 9가지 제스쳐 지원하기 (WM_GESTURE)
  3. 멀티터치 Raw 데이터를 사용 (WM_TOUCH)
  4. Manipulation and Inertia 활용
  5. WPF4 멀티터치 프로그래밍
  6. 실버라이트 4의 멀티터치 프로그래밍


관련 어셈블리(DLL) 다운로드 하기
시작하기전에 관련 DLL을 다운로드 해서 사용해야 합니다. 윈도우 7의 멀티터치 지원 API들은 모두 Win32 네이티브 API들입니다. Win32 환경에서는 직접 호출하여 사용을 할 수 있지만 .NET 프레임워크 환경에서는 직접 호출하여 사용할 수 없습니다.

따라서 .NET 프레임워크 환경에서 Win32 환경의 멀티터치 API를 호출할 수 있도록 해줘야 하는데 이 라이브러리가 공개되어 있습니다. Windows 7 Multitouch .NET Interop Sample Library 링크를 통해서 소스코드까지 다운로드 받을 수 있으며 비주얼 스튜디오를 이용하여 빌드하면 결과로 나오는 어셈블리 3가지 Windows7.Multitouch.dll, Windows7.Multitouch.WPF.dll, Windows7.Multitouch.WinForms.dll를 .NET 응용프로그램 소스코드에 참조로 등록하여 사용해야 합니다. 준비를 해 주세요.

MICROSOFT PUBLIC LICENSE 를 따르고 있으므로 꼭 다운로드 하셔야 합니다.

9가지 정해져 있는 멀티터치 제스쳐 (WM_GESTURE 메세지)

WM_GESTURE 메시지를 이용한 멀티터치 개발은 가장 쉽고 단순하게 윈도우 7에서 멀티터치를 구현하는 방법으로 정해진 9가지의 제스처를 이용하는 방법입니다. 먼저 9가지의 제스처를 아래 그림으로 살펴봅시다.


(출처 : MSDN, http://msdn.microsoft.com/ko-kr/library/dd940543(v=VS.85).aspx)

그림에서 보면 9가지 제스처와 그에 상응하는 마우스와 키보드 사용법을 매치 시켜놨습니다. 모든 제스처가 하나 또는 두 개의 터치입력으로 이루어진 제스처들인데 이는 두 개의 터치입력만 가능한 디바이스에서도 문제가 없도록 디자인을 했나봅니다.

어찌되었건 Windows 7은 멀티터치 디바이스에서 전달한 데이터를 가지고 저런 제스쳐를 만들어 프로그래머에게 던져 줍니다. 프로그래머는 그 이벤트를 받아서 마치 마우스나 키보드 컨트롤 하듯이 프로그래밍을 하면 쉽게 우리의 응용프로그램에 멀티터치 기능을 추가할 수 있습니다. 프로그래밍을 해봅시다.

다시 말하지만 Windows 7의 멀티터치 지원은 Windows의 Native API이므로 우리는 닷넷에서 사용가능하도록 랩핑된 어셈블리를 사용하겠습니다. 그리고 WPF 환경에서 샘플을 만들 예정이라서 주로 Windows7.Multitouch.WPF.dll 에 있는 내용을 사용하겠습니다.

소스코드 다운로드 하기 : Win7MultitouchCapabilities.zip (Visual Studion 2008, WPF)



멀티터치를 지원하는지 확인하기
먼저 해야 할 작업은 무엇보다 응용프로그램이 실행된 환경이 멀티터치가 가능한 환경인지 확인을 하는 하는 것입니다. 이 작업은 Win32 네이티브 API 중에서 GetSystemMetrics() 함수의 호출을 통해서 확인 할 수 합니다. 반환되는 값을 분석하면 추가적으로 몇 개의 멀티터치 포인트를 지원하는지, 터치 디바이스가 내장인지 외장인지에 대해서도 알 수 있다. .NET 환경에서는 아래 코드로 확인 할 수 있다. 우리는 이런 검사를 통해서 멀티터치가 가능한 상태에서의 반응과 가능하지 않은 상태에서의 반응을 다르게 프로그래밍 할 수도 있을 것입니다. 여기에서는 프로그램을 종료시켜 버렸는데 사실 좋은 프로그래밍이 아니죠.

using Windows7.Multitouch;

 

if (!GestureHandler.DigitizerCapabilities.IsMultiTouchReady)

{

MessageBox.Show("Multitouch is not availible");

Environment.Exit(1);

}

else

{

int numberoftouches =GestureHandler.DigitizerCapabilities.MaxumumTouches;

MessageBox.Show(numberoftouches + "개의 터치입력 가능");

}


저는 멀티터치 디바이스가 없는 PC에서 작업을 하고 있어서 Multitouch Vista라는 오픈소소의 도움을 받고 있는데요. 이 상태에서 실행시켜보니 아래처럼 255개의 포인트를 지원하네요. 멀티마우스를 손가락으로 시뮬레이션하기 때문에 최대값을 저렇게 지정을 했나봅니다. 실제로 마우스 255개를 붙이면 될까요? ^^



9개의 제스쳐 활용하기
Windows 7의 Native API가 전달해주는 구조체는 MSDN에서 확인 할 수 있는데 조금 복잡해 보일 수 도 있습니다. 하지만 닷넷, WPF에서는 우리가 기존에 마우스 이벤트를 다뤘던 경험만 있으면 어려워 보이는 9가지 제스쳐를 쉽게 구현할 수 있습니다. 먼저 코드를 살펴봅시다.

using Windows7.Multitouch;

GestureHandler _gestureHandler = Factory.CreateGestureHandler(this);

 

_gestureHandler.Pan += ProcessPan;

_gestureHandler.Rotate += ProcessRotate;

_gestureHandler.PressAndTap += ProcessPressAndTap;

_gestureHandler.TwoFingerTap += ProcessTwoFingerTap;

_gestureHandler.Zoom += ProcessZoom;

private void ProcessPan(object sender, GestureEventArgs args)

{

trans.X += args.PanTranslation.Width;

trans.Y += args.PanTranslation.Height;

}

private void ProcessRotate(object sender, GestureEventArgs args)

{

rotate.Angle -= args.RotateAngle * 180 / Math.PI;

}

private void ProcessPressAndTap(object sender, GestureEventArgs args)

{

rectangle.Fill = new SolidColorBrush(Colors.Blue);

}

 

private void ProcessTwoFingerTap(object sender, GestureEventArgs args)

{

rectangle.Fill = new SolidColorBrush(Colors.Red);

}

private void ProcessZoom(object sender, GestureEventArgs args)

{

scale.ScaleX *= args.ZoomFactor;

scale.ScaleY *= args.ZoomFactor;

}


원하는 제스쳐 선택하고 이벤트 핸들러를 등록한 다음 이벤트 핸들러에서 전달되는 매개변수 값을 이용하여 프로그래밍을 하면 됩니다. 참 쉽죠 잉~~. 아래 코드를 다운로드 하여 실행 시켜 봅시다. 

소스코드 다운로드 : WpfTouchGesture.zip (Visual Studion 2008, WPF)


실행한 영상을 아래 첨부 합니다. 마이크가 없어서 목소리 없이 그냥 ... 중간에 손가락을 빨간색 점으로 표시하고 박스도 빨간색이니 포인트가 안보여서 다시 소스를 보는 장면이 있는데 소스를 보니 Two Finger Tap이 박스의 색을 파란색으로 바꿔줍니다.



영상이 안보이면 http://tvpot.daum.net/my/ClipView.do?ownerid=ADowB8WbINw0&clipid=25736362

9개의 제스쳐를 활용한 프로그래밍은 단순해서 좋지만 한가지 단점이 있습니다. 한번에 하나의 제스쳐만 가능하기 때문에 사각형 박스를 돌리면서 동시에 이동을 할 수가 없습니다. 그래서 조금 부자연스럽다고 느끼게 됩니다.

하지만 응용프로그램의 설계에 따라서 필요한 제스쳐를 선택하고 적절히 사용한다면 문제가 없을 것입니다.


WRITTEN BY
ONESTONE

트랙백  0 , 댓글  0개가 달렸습니다.
secret