I don't see "2D not 3D" as a valid reason to not use vertex buffers and textures here. There's absolutely nothing about 2D that precludes their use. Perhaps you're drawing using StretchRect calls instead of DrawPrimitive? If so, then maybe you should look at the ID3DXSprite interface for an alternative, or else use vertex buffers and textures with the D3DFVF_XYZRHW option in an FVF (or D3DDECLUSAGE_POSITIONT in a declaration) to specify 2D coords without needing to worry about transforms (you can also use DrawPrimitiveUP to totally avoid vertex buffers if you wish - generally not recommended but good enough for simple programs where absolute performance isn't a requirement).
StretchRect itself can't do alpha blending; it merely transfers the contents of one surface to another. You can't use a surface in a shader; you need to use textures. So if you're using surfaces and StretchRect then you need to get away from that.