as always, efficiency is the result of good software design. One way of speeding things up is to use caches.
DrawMsg() is called by Cinema whenever Cinema things something might have changed. I don't think you can do anything about that.
You have to make sure that within DrawMsg() you only draw and do nothing else. Why are you loading the bitmap in the context of DrawMsg()? Why are you scaling the images in the context of DrawMsg()? Why not earlier?
I guess at some point, your program knowns what images to display. At that point you could load all these (scaled) images into a cache. Then in DrawMsg(), you can simply access the data in that cache.
Compare e.g. BaseShader.InitRender() which is used to do all the heavy lifting, so that BaseShader.Sample() can be fast.
Depending on the reason for the redraw, you could optimize further. E.g. you could use a GeClipMap to draw whatever you want into a BaseBitmap and simply draw that BaseBitmap in the context of DrawMsg().
Speed is the result of software design. Caches can help, but of course they increase code complexity and memory footprint.